MT6620: add the new driver JB2 V1.0
authorxbw <xbw@rock-chips.com>
Mon, 20 May 2013 07:22:32 +0000 (15:22 +0800)
committerxbw <xbw@rock-chips.com>
Mon, 20 May 2013 07:22:32 +0000 (15:22 +0800)
288 files changed:
arch/arm/mach-rk30/include/mach/mtk_wcn_cmb_stub.h
arch/arm/mach-rk3188/include/mach/mtk_wcn_cmb_stub.h [changed mode: 0644->0755]
drivers/mtk_wcn_combo/Kconfig [new file with mode: 0755]
drivers/mtk_wcn_combo/Makefile [new file with mode: 0755]
drivers/mtk_wcn_combo/Module.symvers [new file with mode: 0755]
drivers/mtk_wcn_combo/common/Makefile [new file with mode: 0755]
drivers/mtk_wcn_combo/common/core/btm_core.c [new file with mode: 0755]
drivers/mtk_wcn_combo/common/core/dbg_core.c [new file with mode: 0755]
drivers/mtk_wcn_combo/common/core/include/btm_core.h [new file with mode: 0755]
drivers/mtk_wcn_combo/common/core/include/dbg_core.h [new file with mode: 0755]
drivers/mtk_wcn_combo/common/core/include/psm_core.h [new file with mode: 0755]
drivers/mtk_wcn_combo/common/core/include/stp_core.h [new file with mode: 0755]
drivers/mtk_wcn_combo/common/core/include/stp_wmt.h [new file with mode: 0755]
drivers/mtk_wcn_combo/common/core/include/wmt_conf.h [new file with mode: 0755]
drivers/mtk_wcn_combo/common/core/include/wmt_core.h [new file with mode: 0755]
drivers/mtk_wcn_combo/common/core/include/wmt_ctrl.h [new file with mode: 0755]
drivers/mtk_wcn_combo/common/core/include/wmt_dbg.h [new file with mode: 0755]
drivers/mtk_wcn_combo/common/core/include/wmt_func.h [new file with mode: 0755]
drivers/mtk_wcn_combo/common/core/include/wmt_ic.h [new file with mode: 0755]
drivers/mtk_wcn_combo/common/core/include/wmt_lib.h [new file with mode: 0755]
drivers/mtk_wcn_combo/common/core/psm_core.c [new file with mode: 0755]
drivers/mtk_wcn_combo/common/core/stp_core.c [new file with mode: 0755]
drivers/mtk_wcn_combo/common/core/stp_exp.c [new file with mode: 0755]
drivers/mtk_wcn_combo/common/core/wmt_conf.c [new file with mode: 0755]
drivers/mtk_wcn_combo/common/core/wmt_core.c [new file with mode: 0755]
drivers/mtk_wcn_combo/common/core/wmt_ctrl.c [new file with mode: 0755]
drivers/mtk_wcn_combo/common/core/wmt_dbg.c [new file with mode: 0755]
drivers/mtk_wcn_combo/common/core/wmt_exp.c [new file with mode: 0755]
drivers/mtk_wcn_combo/common/core/wmt_func.c [new file with mode: 0755]
drivers/mtk_wcn_combo/common/core/wmt_ic_6620.c [new file with mode: 0755]
drivers/mtk_wcn_combo/common/core/wmt_ic_6628.c [new file with mode: 0755]
drivers/mtk_wcn_combo/common/core/wmt_lib.c [new file with mode: 0755]
drivers/mtk_wcn_combo/common/include/mtk_wcn_cmb_hw.h [new file with mode: 0755]
drivers/mtk_wcn_combo/common/include/stp_exp.h [new file with mode: 0755]
drivers/mtk_wcn_combo/common/include/wmt.h [new file with mode: 0755]
drivers/mtk_wcn_combo/common/include/wmt_exp.h [new file with mode: 0755]
drivers/mtk_wcn_combo/common/include/wmt_plat.h [new file with mode: 0755]
drivers/mtk_wcn_combo/common/include/wmt_plat_stub.h [new file with mode: 0755]
drivers/mtk_wcn_combo/common/linux/hif_sdio.c [new file with mode: 0755]
drivers/mtk_wcn_combo/common/linux/hif_sdio_chrdev.c [new file with mode: 0755]
drivers/mtk_wcn_combo/common/linux/include/hif_sdio.h [new file with mode: 0755]
drivers/mtk_wcn_combo/common/linux/include/hif_sdio_chrdev.h [new file with mode: 0755]
drivers/mtk_wcn_combo/common/linux/include/mach/mtk_wcn_cmb_stub.h [new file with mode: 0755]
drivers/mtk_wcn_combo/common/linux/include/osal.h [new file with mode: 0755]
drivers/mtk_wcn_combo/common/linux/include/osal_typedef.h [new file with mode: 0755]
drivers/mtk_wcn_combo/common/linux/include/stp_dbg.h [new file with mode: 0755]
drivers/mtk_wcn_combo/common/linux/include/stp_sdio.h [new file with mode: 0755]
drivers/mtk_wcn_combo/common/linux/include/wmt_dev.h [new file with mode: 0755]
drivers/mtk_wcn_combo/common/linux/include/wmt_tm.h [new file with mode: 0755]
drivers/mtk_wcn_combo/common/linux/osal.c [new file with mode: 0755]
drivers/mtk_wcn_combo/common/linux/stp_chrdev_bt.c [new file with mode: 0755]
drivers/mtk_wcn_combo/common/linux/stp_chrdev_gps.c [new file with mode: 0755]
drivers/mtk_wcn_combo/common/linux/stp_dbg.c [new file with mode: 0755]
drivers/mtk_wcn_combo/common/linux/stp_uart.c [new file with mode: 0755]
drivers/mtk_wcn_combo/common/linux/wmt_chrdev_wifi.c [new file with mode: 0755]
drivers/mtk_wcn_combo/common/linux/wmt_dev.c [new file with mode: 0755]
drivers/mtk_wcn_combo/common/linux/wmt_tm.c [new file with mode: 0755]
drivers/mtk_wcn_combo/common/platform/rockchip/mtk_wcn_cmb_hw.c [new file with mode: 0755]
drivers/mtk_wcn_combo/common/platform/rockchip/mtk_wcn_cmb_stub_rockchip.c [new file with mode: 0755]
drivers/mtk_wcn_combo/common/platform/rockchip/wmt_plat_rockchip.c [new file with mode: 0755]
drivers/mtk_wcn_combo/common/platform/rockchip/wmt_plat_stub.c [new file with mode: 0755]
drivers/mtk_wcn_combo/common/platform/sample/mtk_wcn_cmb_hw.c [new file with mode: 0755]
drivers/mtk_wcn_combo/common/platform/sample/mtk_wcn_cmb_stub_sample.c [new file with mode: 0755]
drivers/mtk_wcn_combo/common/platform/sample/wmt_plat_sample.c [new file with mode: 0755]
drivers/mtk_wcn_combo/common/platform/sample/wmt_plat_stub.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_bt/Makefile [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_bt/include/bt_conf.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_bt/include/hci_stp.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_bt/linux/hci_stp.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/Makefile [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/core/fm_config.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/core/fm_eint.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/core/fm_link.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/core/fm_main.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/core/fm_module.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/core/fm_patch.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/core/fm_rds_parser.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/core/fm_utils.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/cust/mt6620/mt6620_fm_cust_cfg.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/cust/mt6626/fm_cust_cfg.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/cust/mt6628/mt6628_fm_cust_cfg.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/inc/fm_config.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/inc/fm_dbg.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/inc/fm_eint.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/inc/fm_err.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/inc/fm_interface.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/inc/fm_ioctl.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/inc/fm_link.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/inc/fm_main.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/inc/fm_patch.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/inc/fm_rds.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/inc/fm_stdlib.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/inc/fm_typedef.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/inc/fm_utils.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6620/inc/mt6620_drv_dsp.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6620/inc/mt6620_fm.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6620/inc/mt6620_fm_cmd.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6620/inc/mt6620_fm_lib.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6620/inc/mt6620_fm_link.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6620/inc/mt6620_fm_reg.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6620/pub/mt6620_fm_cmd.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6620/pub/mt6620_fm_config.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6620/pub/mt6620_fm_eint.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6620/pub/mt6620_fm_lib.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6620/pub/mt6620_fm_link.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6620/pub/mt6620_fm_rds.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6626/inc/mt6626_drv_dsp.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6626/inc/mt6626_fm.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6626/inc/mt6626_fm_cmd.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6626/inc/mt6626_fm_lib.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6626/inc/mt6626_fm_link.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6626/inc/mt6626_fm_reg.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6626/piv/mt6626_fm_priv.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6626/piv/mt6626_fm_priv.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6626/pub/mt6626_fm_cmd.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6626/pub/mt6626_fm_eint.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6626/pub/mt6626_fm_lib.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6626/pub/mt6626_fm_link.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6626/pub/mt6626_fm_rds.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6628/inc/mt6628_drv_dsp.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6628/inc/mt6628_fm.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6628/inc/mt6628_fm_cmd.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6628/inc/mt6628_fm_lib.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6628/inc/mt6628_fm_link.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6628/inc/mt6628_fm_reg.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6628/pub/mt6628_fm_cmd.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6628/pub/mt6628_fm_config.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6628/pub/mt6628_fm_eint.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6628/pub/mt6628_fm_lib.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6628/pub/mt6628_fm_link.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/mt6628/pub/mt6628_fm_rds.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/private/Makefile [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/private/inc/fm_priv_log.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_fm/private/inc/fm_private.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/Makefile [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/Makefile [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/Makefile [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/common/dump.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/common/wlan_bow.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/common/wlan_lib.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/common/wlan_oid.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/common/wlan_p2p.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/CFG_Wifi_File.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/config.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/debug.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/link.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/aa_fsm.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/ais_fsm.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/assoc.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/auth.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/bow_fsm.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/bss.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/cnm.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/cnm_mem.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/cnm_scan.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/cnm_timer.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/hem_mbox.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/mib.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_assoc.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_bss.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_fsm.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_func.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_ie.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_rlm.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_rlm_obss.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_scan.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_state.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/privacy.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/rate.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/rlm.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/rlm_domain.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/rlm_obss.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/rlm_protection.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/roaming_fsm.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/rsn.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/scan.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/sec_fsm.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/swcr.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/wapi.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/wlan_typedef.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/wnm.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/adapter.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/bow.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/cmd_buf.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/hal.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/hif_rx.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/hif_tx.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/mac.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/mt6620_reg.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/nic.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/nic_rx.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/nic_tx.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/p2p.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/p2p_cmd_buf.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/p2p_mac.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/p2p_nic.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/p2p_nic_cmd_event.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/que_mgt.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/wlan_def.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic_cmd_event.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic_init_cmd_event.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/p2p_precomp.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/p2p_typedef.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/precomp.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/pwr_mgt.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/queue.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/rftest.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/typedef.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/wlan_bow.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/wlan_lib.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/wlan_oid.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/wlan_p2p.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/aaa_fsm.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/ais_fsm.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/assoc.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/auth.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/bss.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/cnm.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/cnm_mem.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/cnm_timer.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/hem_mbox.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/mib.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_assoc.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_bss.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_fsm.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_func.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_ie.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_rlm.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_rlm_obss.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_scan.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_state.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/privacy.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/rate.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/rlm.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/rlm_domain.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/rlm_obss.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/rlm_protection.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/roaming_fsm.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/rsn.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/saa_fsm.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/scan.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/scan_fsm.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/sec_fsm.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/swcr.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/wapi.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/wnm.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/cmd_buf.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/nic.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/nic_cmd_event.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/nic_pwr_mgt.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/nic_rx.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/nic_tx.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/p2p_nic.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/que_mgt.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_bow.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_cfg80211.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_init.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_kal.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_p2p.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_p2p_cfg80211.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_p2p_init.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_p2p_kal.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_proc.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_rst.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_wext.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_wext_priv.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/hif/sdio/arm.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/hif/sdio/include/hif.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/hif/sdio/include/hif_sdio.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/hif/sdio/include/mtk_porting.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/hif/sdio/sdio.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/hif/sdio/x86.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_cfg80211.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_kal.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_os.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_p2p_ioctl.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_p2p_kal.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_p2p_os.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_rst.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_sec.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_typedef.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_wext.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_wext_priv.h [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/platform.c [new file with mode: 0755]
drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/version.h [new file with mode: 0755]
drivers/mtk_wcn_combo/gps/Makefile [new file with mode: 0755]
drivers/mtk_wcn_combo/gps/gps.c [new file with mode: 0755]
net/wireless/Kconfig [changed mode: 0644->0755]

index 18682c0d69ecc8f40505a2527bee0862b18669cd..ec4d5f19524d1b9430989b7ed02dc1f468175edf 100755 (executable)
@@ -1,39 +1,3 @@
-/* Copyright Statement:
- *
- * This software/firmware and related documentation ("MediaTek Software") are
- * protected under relevant copyright laws. The information contained herein
- * is confidential and proprietary to MediaTek Inc. and/or its licensors.
- * Without the prior written permission of MediaTek inc. and/or its licensors,
- * any reproduction, modification, use or disclosure of MediaTek Software,
- * and information contained herein, in whole or in part, shall be strictly prohibited.
- *
- * MediaTek Inc. (C) 2010. All rights reserved.
- *
- * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
- * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
- * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
- * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
- * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
- * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
- * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
- * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
- * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
- * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
- * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
- * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
- * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
- * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
- * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
- * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
- *
- * The following software/firmware and/or related documentation ("MediaTek Software")
- * have been modified by MediaTek Inc. All revisions are subject to any receiver's
- * applicable license agreements with MediaTek Inc.
- */
-
-
 /*! \file
     \brief  Declaration of library functions
 
 /*! \file
     \brief  Declaration of library functions
 
 #ifndef _MTK_WCN_CMB_STUB_H_
 #define _MTK_WCN_CMB_STUB_H_
 
 #ifndef _MTK_WCN_CMB_STUB_H_
 #define _MTK_WCN_CMB_STUB_H_
 
+#include <linux/types.h>
+       typedef enum {
+               COMBO_AUDIO_STATE_0 = 0, /* 0000: BT_PCM_OFF & FM analog (line in/out) */
+               COMBO_AUDIO_STATE_1 = 1, /* 0001: BT_PCM_ON & FM analog (in/out) */
+               COMBO_AUDIO_STATE_2 = 2, /* 0010: BT_PCM_OFF & FM digital (I2S) */
+               COMBO_AUDIO_STATE_3 = 3, /* 0011: BT_PCM_ON & FM digital (I2S) (invalid in 73evb & 1.2 phone configuration) */
+               COMBO_AUDIO_STATE_MAX = 4,
+       } COMBO_AUDIO_STATE;
+       
+       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_MAX,
+       } COMBO_IF;
+       
+       
+       /******************************************************************************
+       *                                       F U N C T I O N   D E C L A R A T I O N S
+       *******************************************************************************
+       */
+       
+       
+       /* [GeorgeKuo] Stub functions for other kernel built-in modules to call.
+        * Keep them unchanged temporarily. Move mt_combo functions to mtk_wcn_combo.
+        */
+       //extern int mt_combo_audio_ctrl_ex(COMBO_AUDIO_STATE state, u32 clt_ctrl);
+       static inline int mt_combo_audio_ctrl(COMBO_AUDIO_STATE state) {
+               //return mt_combo_audio_ctrl_ex(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 board_sdio_ctrl (unsigned int sdio_port_num, unsigned int on);
+//#include <mach/mt_combo.h> jake 
 /*******************************************************************************
 *                         C O M P I L E R   F L A G S
 ********************************************************************************
 /*******************************************************************************
 *                         C O M P I L E R   F L A G S
 ********************************************************************************
@@ -129,32 +142,6 @@ typedef enum {
     CMB_STUB_AIF_CTRL_MAX = 2,
 } CMB_STUB_AIF_CTRL;
 
     CMB_STUB_AIF_CTRL_MAX = 2,
 } CMB_STUB_AIF_CTRL;
 
-#if 1 /* copied from mt_combo.h */
-typedef enum {
-    COMBO_AUDIO_STATE_0 = 0, /* 0000: BT_PCM_OFF & FM analog (line in/out) */
-    COMBO_AUDIO_STATE_1 = 1, /* 0001: BT_PCM_ON & FM analog (in/out) */
-    COMBO_AUDIO_STATE_2 = 2, /* 0010: BT_PCM_OFF & FM digital (I2S) */
-    COMBO_AUDIO_STATE_3 = 3, /* 0011: BT_PCM_ON & FM digital (I2S) (invalid in 73evb & 1.2 phone configuration) */
-    COMBO_AUDIO_STATE_MAX = 4,
-} COMBO_AUDIO_STATE;
-
-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_MAX,
-} COMBO_IF;
-#endif
-
 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 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);
@@ -171,11 +158,17 @@ typedef struct _CMB_STUB_CB_ {
 ********************************************************************************
 */
 
 ********************************************************************************
 */
 
+
+
 /*******************************************************************************
 *                           P R I V A T E   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   D E C L A R A T I O N S
 ********************************************************************************
@@ -186,28 +179,23 @@ 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);
 
 
 extern int mtk_wcn_cmb_stub_aif_ctrl (CMB_STUB_AIF_X state, CMB_STUB_AIF_CTRL ctrl);
 
-#if 0 /* remove obsolete audio_ctrl APIs. Use stub_aif_ctrl()! */
-/* [GeorgeKuo] Stub functions for other kernel built-in modules to call.
- * Keep them unchanged temporarily. Move mt_combo functions to mtk_wcn_combo.
- */
-extern int mtk_wcn_cmb_stub_audio_ctrl_ex(COMBO_AUDIO_STATE state, u32 clt_ctrl);
-static inline int mtk_wcn_cmb_stub_audio_ctrl(COMBO_AUDIO_STATE state) {
-    return mtk_wcn_cmb_stub_audio_ctrl_ex(state, 1);
-}
+// TODO: [FixMe][GeorgeKuo]: put prototypes into mt_combo.h for board.c temporarily for non-finished porting
+// TODO: old: rfkill->board.c->mt_combo->wmt_lib_plat
+// TODO: new: rfkill->mtk_wcn_cmb_stub_alps->wmt_plat_alps
+#if 0
+extern int mtk_wcn_cmb_stub_func_ctrl(unsigned int type, unsigned int on);
 #endif
 
 #endif
 
-/* 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 mt_combo_plt_enter_deep_idle(COMBO_IF src);
-extern int mt_combo_plt_exit_deep_idle(COMBO_IF src);
-
 /*******************************************************************************
 *                              F U N C T I O N S
 ********************************************************************************
 */
 
 /*******************************************************************************
 *                              F U N C T I O N S
 ********************************************************************************
 */
 
+
 #endif /* _MTK_WCN_CMB_STUB_H_ */
 
 #endif /* _MTK_WCN_CMB_STUB_H_ */
 
+
+
+
+
+
old mode 100644 (file)
new mode 100755 (executable)
index 18682c0..ec4d5f1
@@ -1,39 +1,3 @@
-/* Copyright Statement:
- *
- * This software/firmware and related documentation ("MediaTek Software") are
- * protected under relevant copyright laws. The information contained herein
- * is confidential and proprietary to MediaTek Inc. and/or its licensors.
- * Without the prior written permission of MediaTek inc. and/or its licensors,
- * any reproduction, modification, use or disclosure of MediaTek Software,
- * and information contained herein, in whole or in part, shall be strictly prohibited.
- *
- * MediaTek Inc. (C) 2010. All rights reserved.
- *
- * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
- * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
- * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
- * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
- * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
- * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
- * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
- * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
- * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
- * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
- * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
- * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
- * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
- * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
- * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
- * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
- *
- * The following software/firmware and/or related documentation ("MediaTek Software")
- * have been modified by MediaTek Inc. All revisions are subject to any receiver's
- * applicable license agreements with MediaTek Inc.
- */
-
-
 /*! \file
     \brief  Declaration of library functions
 
 /*! \file
     \brief  Declaration of library functions
 
 #ifndef _MTK_WCN_CMB_STUB_H_
 #define _MTK_WCN_CMB_STUB_H_
 
 #ifndef _MTK_WCN_CMB_STUB_H_
 #define _MTK_WCN_CMB_STUB_H_
 
+#include <linux/types.h>
+       typedef enum {
+               COMBO_AUDIO_STATE_0 = 0, /* 0000: BT_PCM_OFF & FM analog (line in/out) */
+               COMBO_AUDIO_STATE_1 = 1, /* 0001: BT_PCM_ON & FM analog (in/out) */
+               COMBO_AUDIO_STATE_2 = 2, /* 0010: BT_PCM_OFF & FM digital (I2S) */
+               COMBO_AUDIO_STATE_3 = 3, /* 0011: BT_PCM_ON & FM digital (I2S) (invalid in 73evb & 1.2 phone configuration) */
+               COMBO_AUDIO_STATE_MAX = 4,
+       } COMBO_AUDIO_STATE;
+       
+       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_MAX,
+       } COMBO_IF;
+       
+       
+       /******************************************************************************
+       *                                       F U N C T I O N   D E C L A R A T I O N S
+       *******************************************************************************
+       */
+       
+       
+       /* [GeorgeKuo] Stub functions for other kernel built-in modules to call.
+        * Keep them unchanged temporarily. Move mt_combo functions to mtk_wcn_combo.
+        */
+       //extern int mt_combo_audio_ctrl_ex(COMBO_AUDIO_STATE state, u32 clt_ctrl);
+       static inline int mt_combo_audio_ctrl(COMBO_AUDIO_STATE state) {
+               //return mt_combo_audio_ctrl_ex(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 board_sdio_ctrl (unsigned int sdio_port_num, unsigned int on);
+//#include <mach/mt_combo.h> jake 
 /*******************************************************************************
 *                         C O M P I L E R   F L A G S
 ********************************************************************************
 /*******************************************************************************
 *                         C O M P I L E R   F L A G S
 ********************************************************************************
@@ -129,32 +142,6 @@ typedef enum {
     CMB_STUB_AIF_CTRL_MAX = 2,
 } CMB_STUB_AIF_CTRL;
 
     CMB_STUB_AIF_CTRL_MAX = 2,
 } CMB_STUB_AIF_CTRL;
 
-#if 1 /* copied from mt_combo.h */
-typedef enum {
-    COMBO_AUDIO_STATE_0 = 0, /* 0000: BT_PCM_OFF & FM analog (line in/out) */
-    COMBO_AUDIO_STATE_1 = 1, /* 0001: BT_PCM_ON & FM analog (in/out) */
-    COMBO_AUDIO_STATE_2 = 2, /* 0010: BT_PCM_OFF & FM digital (I2S) */
-    COMBO_AUDIO_STATE_3 = 3, /* 0011: BT_PCM_ON & FM digital (I2S) (invalid in 73evb & 1.2 phone configuration) */
-    COMBO_AUDIO_STATE_MAX = 4,
-} COMBO_AUDIO_STATE;
-
-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_MAX,
-} COMBO_IF;
-#endif
-
 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 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);
@@ -171,11 +158,17 @@ typedef struct _CMB_STUB_CB_ {
 ********************************************************************************
 */
 
 ********************************************************************************
 */
 
+
+
 /*******************************************************************************
 *                           P R I V A T E   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   D E C L A R A T I O N S
 ********************************************************************************
@@ -186,28 +179,23 @@ 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);
 
 
 extern int mtk_wcn_cmb_stub_aif_ctrl (CMB_STUB_AIF_X state, CMB_STUB_AIF_CTRL ctrl);
 
-#if 0 /* remove obsolete audio_ctrl APIs. Use stub_aif_ctrl()! */
-/* [GeorgeKuo] Stub functions for other kernel built-in modules to call.
- * Keep them unchanged temporarily. Move mt_combo functions to mtk_wcn_combo.
- */
-extern int mtk_wcn_cmb_stub_audio_ctrl_ex(COMBO_AUDIO_STATE state, u32 clt_ctrl);
-static inline int mtk_wcn_cmb_stub_audio_ctrl(COMBO_AUDIO_STATE state) {
-    return mtk_wcn_cmb_stub_audio_ctrl_ex(state, 1);
-}
+// TODO: [FixMe][GeorgeKuo]: put prototypes into mt_combo.h for board.c temporarily for non-finished porting
+// TODO: old: rfkill->board.c->mt_combo->wmt_lib_plat
+// TODO: new: rfkill->mtk_wcn_cmb_stub_alps->wmt_plat_alps
+#if 0
+extern int mtk_wcn_cmb_stub_func_ctrl(unsigned int type, unsigned int on);
 #endif
 
 #endif
 
-/* 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 mt_combo_plt_enter_deep_idle(COMBO_IF src);
-extern int mt_combo_plt_exit_deep_idle(COMBO_IF src);
-
 /*******************************************************************************
 *                              F U N C T I O N S
 ********************************************************************************
 */
 
 /*******************************************************************************
 *                              F U N C T I O N S
 ********************************************************************************
 */
 
+
 #endif /* _MTK_WCN_CMB_STUB_H_ */
 
 #endif /* _MTK_WCN_CMB_STUB_H_ */
 
+
+
+
+
+
diff --git a/drivers/mtk_wcn_combo/Kconfig b/drivers/mtk_wcn_combo/Kconfig
new file mode 100755 (executable)
index 0000000..d47905f
--- /dev/null
@@ -0,0 +1,149 @@
+menu "MediaTek Connectivity Combo Chip Config"
+
+config MTK_COMBO
+       bool "MediaTek Connectivity Combo Chip Support"
+       help
+         MTK connectivity combo chip driver for MT6620
+
+#
+# MTK Combo Chip Selection
+#
+choice
+       prompt "Select Chip"
+       depends on MTK_COMBO
+
+config MTK_COMBO_CHIP_MT6620
+       bool "MT6620"
+
+#config MTK_COMBO_CHIP_MT6628
+#      bool "MT6628"
+endchoice
+
+#
+# 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/*
+
+config MTK_COMBO_DRIVER_VERSION_JB2
+       depends on MTK_COMBO
+       bool "MediaTek Connectivity Combo Driver version is JB2 V1.0"
+       default n
+
+       help
+          MTK driver V3.1 will use a different configuration about SDIO.
+
+#
+# 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_BT
+       tristate "MediaTek Combo Chip BT driver"
+       depends on MTK_COMBO
+       help
+         MTK BT /dev/stpbt driver for Bluedroid (mtk_stp_bt.ko)
+        
+config MTK_COMBO_BT_HCI
+       tristate "MediaTek Combo Chip BlueZ driver"
+       depends on BT && MTK_COMBO
+       help
+         MTK BT driver for BlueZ (hci_stp.ko)
+
+config MTK_COMBO_FM
+       tristate "MediaTek Combo Chip FM driver"
+       depends on MTK_COMBO
+       help
+         MTK FM /dev/fm driver (mt6620_fm_drv.ko, mtk_fm_priv.ko)
+
+config MTK_COMBO_WIFI
+       tristate "MediaTek Combo Chip Wi-Fi support"
+       depends on MTK_COMBO
+       depends on MMC
+       depends on IPV6
+       select WIRELESS_EXT
+       select WEXT_PRIV
+       help
+         This module adds support for wireless adapters based on
+         MTK MT6620 chipset.
+
+         This driver uses the kernel's wireless extensions subsystem.
+
+         If you choose to build a module, it'll be called dhd. Say M if
+         unsure.
+
+#config MTK_COMBO_WIFI_FW_PATH
+#      depends on MTK_COMBO_WIFI
+#      string "Firmware path"
+#      default "/system/etc/firmware/WIFI_RAM_CODE"
+#      help
+#        Path to the firmware file
+
+config MTK_COMBO_WIFI_DEBUG
+       depends on MTK_COMBO_WIFI
+       bool "Enable debug output from MT6620 driver"
+       help
+         Enable debug messages output from MT6620 driver
+
+config MTK_COMBO_WIFI_PROC
+       depends on MTK_COMBO_WIFI
+       bool "Enable procfs support"
+       help
+         Enable procfs support.
+
+#config MTK_WAPI_SUPPORT
+#      depends on MTK_COMBO_WIFI
+#      bool "Enable WAPI support in MT6620 driver"
+#      help
+#        Enable WAPI support for devices using MT6620
+
+choice
+       prompt "Host Interface"
+       depends on MTK_COMBO_WIFI
+
+config MTK_COMBO_WIFI_HIF_SDIO1
+       bool "SDIO #1"
+       depends on MTK_COMBO_WIFI
+endchoice
+
+
+config MTK_GPS
+       tristate "MediaTek GPS Support"
+       help
+         MTK GPS /dev/gps driver (mtk_gps.ko)
+
+config MTK_COMBO_GPS
+       tristate "MediaTek Combo Chip GPS driver"
+       depends on MTK_COMBO && MTK_GPS
+       help
+         MTK GPS /dev/stpgps driver (mtk_stp_gps.ko)
+
+endmenu
diff --git a/drivers/mtk_wcn_combo/Makefile b/drivers/mtk_wcn_combo/Makefile
new file mode 100755 (executable)
index 0000000..7d16890
--- /dev/null
@@ -0,0 +1,60 @@
+# Copyright Statement:
+#
+# This software/firmware and related documentation ("MediaTek Software") are
+# protected under relevant copyright laws. The information contained herein
+# is confidential and proprietary to MediaTek Inc. and/or its licensors.
+# Without the prior written permission of MediaTek inc. and/or its licensors,
+# any reproduction, modification, use or disclosure of MediaTek Software,
+# and information contained herein, in whole or in part, shall be strictly prohibited.
+#
+# MediaTek Inc. (C) 2010. All rights reserved.
+#
+# BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+# THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+# RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+# AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+# NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+# SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+# SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+# THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+# THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+# CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+# SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+# STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+# CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+# AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+# OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+# MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+#
+# The following software/firmware and/or related documentation ("MediaTek Software")
+# have been modified by MediaTek Inc. All revisions are subject to any receiver's
+# applicable license agreements with MediaTek Inc.
+
+
+# combo driver: MT6620
+# 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
+       #subdir-ccflags-y += -I$(src)/common/include -I$(src)/common/linux/include 
+       #used for binary release script
+    #KERNEL_PATH := $(pwd)
+    #OBJ_PATH := $(pwd)  
+       obj-$(CONFIG_MTK_COMBO) += common/
+       obj-$(CONFIG_MTK_COMBO_FM) += drv_fm/
+       obj-$(CONFIG_MTK_COMBO_WIFI) += drv_wlan/
+
+       #Use BT HCI driver
+       obj-$(CONFIG_MTK_COMBO_BT_HCI) += drv_bt/
+       obj-$(CONFIG_MTK_GPS) += gps/
+
+# 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/mtk_wcn_combo/Module.symvers b/drivers/mtk_wcn_combo/Module.symvers
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/drivers/mtk_wcn_combo/common/Makefile b/drivers/mtk_wcn_combo/common/Makefile
new file mode 100755 (executable)
index 0000000..35c5900
--- /dev/null
@@ -0,0 +1,79 @@
+#ccflags-y += -I$(src)/core/include
+ccflags-y += -I$(src)/linux/include -I$(src)/core/include -I$(src)/include -I$(src)/
+ccflags-y += -DWMT_PLAT_APEX=1
+ccflags-y += -DWMT_PLAT_ALPS=0
+ccflags-y += -DWMT_UART_RX_MODE_WORK=1 # 1. work thread 0. tasklet
+#ifeq ($(MTK_COMBO_CHIP), MT6628)
+#EXT_FLAG=
+#else
+#EXT_FLAG=_mt6628
+#endif
+EXT_FLAG=
+COMMON_SRC_PATH := $(src)
+COMMON_OBJ_PATH := $(src)
+
+# WMT DRIVER
+obj-$(CONFIG_MTK_COMBO_COMM) += 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_6620.o core/wmt_lib.o core/wmt_conf.o core/wmt_dbg.o core/wmt_exp.o
+
+#ifeq ($(MTK_COMBO_CHIP), MT6628)
+mtk_stp_wmt$(EXT_FLAG)-objs    += core/wmt_ic_6628.o
+#endif
+# WMT DRIVER-linux private part
+mtk_stp_wmt$(EXT_FLAG)-objs    += linux/wmt_dev.o
+mtk_stp_wmt$(EXT_FLAG)-objs    += linux/wmt_tm.o
+
+# WMT DRIVER-OSAL
+mtk_stp_wmt$(EXT_FLAG)-objs    += linux/osal.o
+# WMT DRIVER-platform implementation
+#ccflags-y += -D WMT_PLAT_ALPS #Jake modify
+
+# WMT DRIVER-platform part, specified by string CONFIG_MTK_COMBO_PLAT_PATH
+PLAT := $(shell echo $(CONFIG_MTK_COMBO_PLAT_PATH))
+
+
+
+#obj-y += platform/$(PLAT)/mtk_wcn_cmb_stub_$(PLAT).o
+mtk_stp_wmt$(EXT_FLAG)-objs    += platform/$(PLAT)/wmt_plat_$(PLAT).o
+mtk_stp_wmt$(EXT_FLAG)-objs    += platform/$(PLAT)/wmt_plat_stub.o
+
+# FIXME: select desired hw according to project configuration
+#ifeq ($(MTK_COMBO_CHIP), MT6628)
+#mtk_stp_wmt$(EXT_FLAG)-objs   += platform/alps/mtk_wcn_cmb_hw_6628.o 
+#else
+mtk_stp_wmt$(EXT_FLAG)-objs    += platform/$(PLAT)/mtk_wcn_cmb_hw.o
+#endif
+
+mtk_stp_wmt$(EXT_FLAG)-objs    += core/stp_exp.o core/stp_core.o core/psm_core.o core/btm_core.o linux/stp_dbg.o
+#ifeq ($(MTK_COMBO_CHIP), MT6628)
+# WMT stub part (built-in kernel image)
+obj-y                  += platform/$(PLAT)/mtk_wcn_cmb_stub_$(PLAT).o
+#endif
+
+obj-$(CONFIG_MTK_COMBO_COMM_UART) += mtk_stp_uart$(EXT_FLAG).o
+mtk_stp_uart$(EXT_FLAG)-objs   := linux/stp_uart.o
+
+
+obj-$(CONFIG_MTK_COMBO_COMM) += mtk_hif_sdio$(EXT_FLAG).o
+mtk_hif_sdio$(EXT_FLAG)-objs   := linux/hif_sdio.o
+mtk_hif_sdio$(EXT_FLAG)-objs   += linux/hif_sdio_chrdev.o
+mtk_hif_sdio$(EXT_FLAG)-objs   += platform/$(PLAT)/mtk_wcn_cmb_hw.o
+mtk_hif_sdio$(EXT_FLAG)-objs   += platform/$(PLAT)/wmt_plat_$(PLAT).o
+mtk_hif_sdio$(EXT_FLAG)-objs   += linux/osal.o
+
+
+# obj-$(CONFIG_MTK_COMBO) += mtk_stp_sdio$(EXT_FLAG).o
+# mtk_stp_sdio$(EXT_FLAG)-objs := linux/stp_sdio.o
+# mtk_stp_sdio$(EXT_FLAG)-objs += linux/osal.o
+
+
+obj-$(CONFIG_MTK_COMBO_BT) += mtk_stp_bt$(EXT_FLAG).o
+mtk_stp_bt$(EXT_FLAG)-objs             := linux/stp_chrdev_bt.o
+
+obj-$(CONFIG_MTK_COMBO_GPS) += mtk_stp_gps$(EXT_FLAG).o
+mtk_stp_gps$(EXT_FLAG)-objs    := linux/stp_chrdev_gps.o
+
+
+obj-$(CONFIG_MTK_COMBO_WIFI) += mtk_wmt_wifi$(EXT_FLAG).o
+mtk_wmt_wifi$(EXT_FLAG)-objs       := linux/wmt_chrdev_wifi.o 
diff --git a/drivers/mtk_wcn_combo/common/core/btm_core.c b/drivers/mtk_wcn_combo/common/core/btm_core.c
new file mode 100755 (executable)
index 0000000..075abb6
--- /dev/null
@@ -0,0 +1,761 @@
+
+
+#include "osal_typedef.h"
+#include "osal.h"
+#include "stp_dbg.h"
+#include "stp_core.h"
+#include "btm_core.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...)   if(gBtmDbgLevel >= STP_BTM_LOG_LOUD){ osal_dbg_print(PFX_BTM "%s: "  fmt, __FUNCTION__ ,##arg);}
+#define STP_BTM_DBG_FUNC(fmt, arg...)    if(gBtmDbgLevel >= STP_BTM_LOG_DBG){ osal_dbg_print(PFX_BTM "%s: "  fmt, __FUNCTION__ ,##arg);}
+#define STP_BTM_INFO_FUNC(fmt, arg...)   if(gBtmDbgLevel >= STP_BTM_LOG_INFO){ osal_dbg_print(PFX_BTM "[I]%s: "  fmt, __FUNCTION__ ,##arg);}
+#define STP_BTM_WARN_FUNC(fmt, arg...)   if(gBtmDbgLevel >= STP_BTM_LOG_WARN){ osal_dbg_print(PFX_BTM "[W]%s: "  fmt, __FUNCTION__ ,##arg);}
+#define STP_BTM_ERR_FUNC(fmt, arg...)    if(gBtmDbgLevel >= STP_BTM_LOG_ERR){  osal_dbg_print(PFX_BTM "[E]%s(%d):ERROR! "   fmt, __FUNCTION__ , __LINE__, ##arg);}
+#define STP_BTM_TRC_FUNC(f)              if(gBtmDbgLevel >= STP_BTM_LOG_DBG){ osal_dbg_print(PFX_BTM "<%s> <%d>\n", __FUNCTION__, __LINE__);}
+
+INT32 gDumplogflag = 0;
+#if WMT_PLAT_ALPS
+extern void dump_uart_history(void);
+#endif
+
+
+#define ASSERT(expr)
+
+MTKSTP_BTM_T stp_btm_i;
+MTKSTP_BTM_T *stp_btm = &stp_btm_i;
+
+const PCHAR g_btm_op_name[]={
+        "STP_OPID_BTM_RETRY",
+        "STP_OPID_BTM_RST",
+        "STP_OPID_BTM_DBG_DUMP",
+        "STP_OPID_BTM_EXIT"
+    };
+
+#if 0
+static PCHAR _stp_pkt_type(INT32 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, "UNKOWN", strlen("UNKOWN")+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  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;
+            if (hdr->dbg_type == STP_DBG_FW_DMP){
+                osal_memcpy(&tmp[index], pkt->raw, pkt->hdr.len);
+
+                if(pkt->hdr.len <= 1500)
+                {
+                    tmp[index + pkt->hdr.len] = '\n';
+                    tmp[index + pkt->hdr.len + 1] = '\0';
+
+                    //printk("\n%s\n+++\n", tmp);
+                    rc = stp_dbg_nl_send((PCHAR)&tmp, 2);
+
+                    while(rc){
+                       nl_retry++;                       
+                       if(nl_retry > 1000){
+                            break;
+                       }                       
+                       STP_BTM_WARN_FUNC("**dump send fails, and retry again.**\n");
+                       osal_msleep(3);
+                       rc = stp_dbg_nl_send((PCHAR)&tmp, 2);
+                       if(!rc){
+                          STP_BTM_WARN_FUNC("****retry again ok!**\n");
+                       }
+                    }                    
+                    //schedule();
+                } else {
+                    STP_BTM_INFO_FUNC("dump entry length is over long\n");
+                    osal_bug_on(0);
+                }
+                retry = 0;
+            }
+        }else
+        {
+            retry ++;
+            osal_msleep(100);
+        }
+    }while((remain > 0) || (retry < 2));
+
+    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) {
+                osal_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");
+                    osal_bug_on(0);
+                }
+                retry = 0;
+            }
+        } else {  
+            retry ++;
+            osal_msleep(100);
+        }
+    }while ((remain > 0) || (retry < 2));
+
+    STP_BTM_INFO_FUNC("Exit..\n");
+    return ret;
+}
+
+#define COMBO_DUMP2AEE
+
+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
+
+    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);
+        break;
+        
+        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; 
+    }
+    else 
+    {
+        //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;
+
+    do {
+        if (!stp_btm || !pOp) 
+        {
+            break;
+        }
+
+        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);
+    }
+
+    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;
+        }
+
+#if 1
+        if(gDumplogflag)
+        {
+            //printk("enter place1\n");    
+            #if WMT_PLAT_ALPS
+            dump_uart_history();
+                       #endif
+            gDumplogflag = 0;
+            continue;
+        }
+#endif
+
+        /* 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 >= 4)?("???"):(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 >= 4)?("???"):(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); 
+        }
+    }
+    
+    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;
+    }
+    else 
+    {
+        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(%d) 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;
+    }
+    else 
+    {
+        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(%d) 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;
+    } else {
+        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(%d) 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){
+
+    P_OSAL_OP     pOp;
+    INT32         bRet;
+    INT32 retval;
+
+    if(stp_btm == NULL)
+    {
+        return STP_BTM_OPERATION_FAIL;
+    }
+    else 
+    {
+        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_DBG_DUMP;
+        pOp->signal.timeoutValue= 0;
+        bRet = _stp_btm_put_act_op(stp_btm, pOp);
+        STP_BTM_DBG_FUNC("OPID(%d) type(%d) 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_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);
+}
+
+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){
+
+    UINT32 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;
+}
+
+
+INT32 stp_notify_btm_dump(MTKSTP_BTM_T *stp_btm)
+{
+    //printk("%s:enter++\n",__func__);
+       if(NULL == stp_btm)
+       {
+           osal_dbg_print("%s: NULL POINTER\n",__func__);
+           return -1;
+       }
+       else
+       {
+           gDumplogflag = 1;
+           osal_trigger_event(&stp_btm->STPd_event);
+           return 0;
+  }
+}
+
diff --git a/drivers/mtk_wcn_combo/common/core/dbg_core.c b/drivers/mtk_wcn_combo/common/core/dbg_core.c
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/drivers/mtk_wcn_combo/common/core/include/btm_core.h b/drivers/mtk_wcn_combo/common/core/include/btm_core.h
new file mode 100755 (executable)
index 0000000..3907f95
--- /dev/null
@@ -0,0 +1,107 @@
+/*! \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"
+
+/*******************************************************************************
+*                         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"
+/*******************************************************************************
+*                    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_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_dump(MTKSTP_BTM_T *stp_btm);
+
+
+
+MTKSTP_BTM_T *stp_btm_init(void);
+
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+
+#endif
diff --git a/drivers/mtk_wcn_combo/common/core/include/dbg_core.h b/drivers/mtk_wcn_combo/common/core/include/dbg_core.h
new file mode 100755 (executable)
index 0000000..c2444f3
--- /dev/null
@@ -0,0 +1,63 @@
+/*! \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/mtk_wcn_combo/common/core/include/psm_core.h b/drivers/mtk_wcn_combo/common/core/include/psm_core.h
new file mode 100755 (executable)
index 0000000..7c95bb0
--- /dev/null
@@ -0,0 +1,209 @@
+/*! \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)
+#if WMT_UART_RX_MODE_WORK
+#define CFG_PSM_CORE_FIFO_SPIN_LOCK 0 
+#else
+#define CFG_PSM_CORE_FIFO_SPIN_LOCK 1
+#endif
+
+
+#define PSM_HANDLING 127
+
+#define STP_PSM_WMT_PS_TASK_HANDLING_TIME  30   //20 milli-seconds
+#define STP_PSM_IDLE_TIME_SLEEP           5000   //temporary for stress testing
+#define STP_PSM_SDIO_IDLE_TIME_SLEEP           100   //temporary for SDIO stress testing
+#define STP_PSM_WAIT_EVENT_TIMEOUT        6000
+
+#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)
+
+
+/* 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;
+#if CFG_PSM_CORE_FIFO_SPIN_LOCK
+typedef OSAL_UNSLEEPABLE_LOCK PSM_FIFO_LOCK, *PPSM_FIFO_LOCK;
+#else
+typedef OSAL_SLEEPABLE_LOCK PSM_FIFO_LOCK, *PPSM_FIFO_LOCK;
+#endif
+
+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*/
+    INT32                   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;
+       
+       PSM_FIFO_LOCK hold_fifo_lock;
+       
+    OSAL_UNSLEEPABLE_LOCK   wq_spinlock;
+    OSAL_SLEEPABLE_LOCK     user_lock;
+       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;
+
+/*******************************************************************************
+*                            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
+********************************************************************************
+*/
+/*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_disable_by_tx_rx_density(MTKSTP_PSM_T *stp_psm, INT32 dir);
+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/mtk_wcn_combo/common/core/include/stp_core.h b/drivers/mtk_wcn_combo/common/core/include/stp_core.h
new file mode 100755 (executable)
index 0000000..5c56685
--- /dev/null
@@ -0,0 +1,555 @@
+/*! \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"
+/*******************************************************************************
+*                         C O M P I L E R   F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                                 M A C R O S
+********************************************************************************
+*/
+
+#define CONFIG_POWER_SAVING_SUPPORT
+#if WMT_UART_RX_MODE_WORK
+#define CFG_STP_CORE_CTX_SPIN_LOCK 0
+#else
+#define CFG_STP_CORE_CTX_SPIN_LOCK 1
+#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...)    if(gStpDbgLvl >= STP_LOG_DBG){  osal_dbg_print(PFX "%s: "  fmt, __FUNCTION__ ,##arg);}
+#define STP_INFO_FUNC(fmt, arg...)   if(gStpDbgLvl >= STP_LOG_INFO){ osal_dbg_print(PFX "%s:[I] "  fmt, __FUNCTION__ ,##arg);}
+#define STP_WARN_FUNC(fmt, arg...)   if(gStpDbgLvl >= STP_LOG_WARN){ osal_dbg_print(PFX "%s:[W] "  fmt, __FUNCTION__ ,##arg);}
+#define STP_ERR_FUNC(fmt, arg...)    if(gStpDbgLvl >= STP_LOG_ERR){  osal_dbg_print(PFX "%s:[E] "   fmt, __FUNCTION__ ,##arg);}
+#define STP_TRC_FUNC(f)              if(gStpDbgLvl >= STP_LOG_DBG){  osal_dbg_print(PFX "<%s> <%d>\n", __FUNCTION__, __LINE__);}
+
+#define STP_DUMP_PACKET_HEAD(a, b, c)     if(gStpDbgLvl >= STP_LOG_PKHEAD){stp_dump_data(a, b, c);}
+#define STP_TRACE_FUNC(fmt, arg...)        if(gStpDbgLvl >= STP_LOG_DBG){  osal_dbg_print(PFX "%s: "  fmt, __FUNCTION__ ,##arg);}
+
+#define MTKSTP_UART_FULL_MODE 0x01
+#define MTKSTP_UART_MAND_MODE 0x02
+#define MTKSTP_SDIO_MODE      0x04
+
+#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 UINT8 *data, const UINT32 size, UINT32 *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);
+
+
+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;
+} 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;
+    #if CFG_STP_CORE_CTX_SPIN_LOCK
+    OSAL_UNSLEEPABLE_LOCK stp_mutex;
+       #else
+       OSAL_SLEEPABLE_LOCK stp_mutex;
+       #endif
+    //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;
+}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 UINT8 *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_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);
+
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+
+#endif /* _STP_CORE_H_ */
diff --git a/drivers/mtk_wcn_combo/common/core/include/stp_wmt.h b/drivers/mtk_wcn_combo/common/core/include/stp_wmt.h
new file mode 100755 (executable)
index 0000000..59cf91a
--- /dev/null
@@ -0,0 +1,89 @@
+/*! \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/mtk_wcn_combo/common/core/include/wmt_conf.h b/drivers/mtk_wcn_combo/common/core/include/wmt_conf.h
new file mode 100755 (executable)
index 0000000..2b2197f
--- /dev/null
@@ -0,0 +1,81 @@
+/*! \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.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/mtk_wcn_combo/common/core/include/wmt_core.h b/drivers/mtk_wcn_combo/common/core/include/wmt_core.h
new file mode 100755 (executable)
index 0000000..c130afe
--- /dev/null
@@ -0,0 +1,460 @@
+/*! \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
+//#include "mtk_wcn_cmb_stub.h" /* for AIF state definition */
+
+/*******************************************************************************
+*                         C O M P I L E R   F L A G S
+********************************************************************************
+*/
+#if defined(MT6620E3) || defined(MT6620E6)   //need modify this part
+#define CFG_CORE_MT6620_SUPPORT 1 /* whether MT6620 is supported or not */
+#else
+#define CFG_CORE_MT6620_SUPPORT 1 /* whether MT6620 is supported or not */
+#endif
+
+#if defined(MT6628)
+#define CFG_CORE_MT6628_SUPPORT 1 /* whether MT6628 is supported or not */
+#else
+#define CFG_CORE_MT6628_SUPPORT 1 /* whether MT6628 is supported or not */
+#endif
+
+// 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_LPBK_CMD_LEN        (5)
+#define WMT_LPBK_BUF_LEN        (1024+WMT_LPBK_CMD_LEN)
+#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_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_SDIO_CTRL = 18,
+    WMT_OPID_FW_COREDMP = 19,
+    WMT_OPID_GPIO_STATE = 20,
+    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 enum _ENUM_WMT_UART_FC_T
+{
+    WMT_UART_NO_FC = 0,
+    WMT_UART_MTK_SW_FC = 1,
+    WMT_UART_LUX_SW_FC = 2,
+    WMT_UART_HW_FC = 3,
+    WMT_UART_MAX
+} ENUM_WMT_UART_FC_T, *P_ENUM_UART_FC_T;
+
+
+typedef struct _WMT_HIF_CONF {
+    UINT32 hifType; // HIF Type
+    UINT32 uartFcCtrl; // UART FC config
+    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 {
+    UCHAR cfgExist;
+
+    UCHAR coex_wmt_ant_mode;
+    UCHAR coex_wmt_wifi_time_ctl;
+    UCHAR coex_wmt_ext_pta_dev_on;
+
+    UCHAR coex_bt_rssi_upper_limit;
+    UCHAR coex_bt_rssi_mid_limit;
+    UCHAR coex_bt_rssi_lower_limit;
+    UCHAR coex_bt_pwr_high;
+    UCHAR coex_bt_pwr_mid;
+    UCHAR coex_bt_pwr_low;
+
+    UCHAR coex_wifi_rssi_upper_limit;
+    UCHAR coex_wifi_rssi_mid_limit;
+    UCHAR coex_wifi_rssi_lower_limit;
+    UCHAR coex_wifi_pwr_high;
+    UCHAR coex_wifi_pwr_mid;
+    UCHAR coex_wifi_pwr_low;
+
+    UCHAR coex_ext_pta_hi_tx_tag;
+    UCHAR coex_ext_pta_hi_rx_tag;
+    UCHAR coex_ext_pta_lo_tx_tag;
+    UCHAR coex_ext_pta_lo_rx_tag;
+    UINT16 coex_ext_pta_sample_t1;
+    UINT16 coex_ext_pta_sample_t2;
+    UCHAR coex_ext_pta_wifi_bt_con_trx;
+
+    UINT32 coex_misc_ext_pta_on;
+    UINT32 coex_misc_ext_feature_set;
+    /*GPS LNA setting*/
+    UCHAR wmt_gps_lna_pin;
+    UCHAR wmt_gps_lna_enable;
+    /*Power on sequence*/
+    UCHAR pwr_on_rtc_slot;
+    UCHAR pwr_on_ldo_slot;
+    UCHAR pwr_on_rst_slot;
+    UCHAR pwr_on_off_slot;
+    UCHAR pwr_on_on_slot;
+       UCHAR 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 = 8,
+    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 {
+    UCHAR *cmd;
+    UINT32 cmdSz;
+    UCHAR *evt;
+    UINT32 evtSz;
+    UCHAR *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
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                           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,
+    PUINT32 pPa1,
+    PUINT32 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 UINT8 *pData,
+    UINT32 size,
+    UINT32 *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);
+
+
+/*******************************************************************************
+*                              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/mtk_wcn_combo/common/core/include/wmt_ctrl.h b/drivers/mtk_wcn_combo/common/core/include/wmt_ctrl.h
new file mode 100755 (executable)
index 0000000..4f1b196
--- /dev/null
@@ -0,0 +1,135 @@
+/*! \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"
+
+/*******************************************************************************
+*                         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_ {
+    UINT32 ctrlId;
+    UINT32 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 power on */
+    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_HOST_BAUDRATE_SET = 9,
+    WMT_CTRL_SDIO_HW = 10, /* enable/disable SDIO1/2 of combo chip */
+    WMT_CTRL_SDIO_FUNC = 11, /* probe/remove STP/Wi-Fi driver in SDIO1/2 of combo chip*/
+    WMT_CTRL_HWIDVER_SET = 12, // TODO: rename this and add chip id information in addition to chip version
+    WMT_CTRL_HWVER_GET = 13, // TODO: [FixMe][GeorgeKuo] remove unused functions
+    WMT_CTRL_STP_RST = 14,
+    WMT_CTRL_GET_WMT_CONF = 15,
+    WMT_CTRL_TX = 16, /* [FixMe][GeorgeKuo]: to be removed by Sean's stp integration */
+    WMT_CTRL_RX = 17, /* [FixMe][GeorgeKuo]: to be removed by Sean's stp integration */
+    WMT_CTRL_RX_FLUSH = 18, /* [FixMe][SeanWang]: to be removed by Sean's stp integration */
+    WMT_CTRL_GPS_SYNC_SET = 19,
+    WMT_CTRL_GPS_LNA_SET = 20,
+    WMT_CTRL_PATCH_SEARCH = 21,
+    WMT_CTRL_CRYSTAL_TRIMING_GET = 22,
+    WMT_CTRL_CRYSTAL_TRIMING_PUT = 23,
+    WMT_CTRL_HW_STATE_DUMP = 24,
+    WMT_CTRL_GET_PATCH_NUM = 25,
+    WMT_CTRL_GET_PATCH_INFO = 26,
+    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 UINT8 *pData,
+    const UINT32 size,
+    UINT32 *writtenSize,
+    const MTK_WCN_BOOL bRawFlag
+    );
+
+
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+
+
+
+#endif /* _WMT_CTRL_H_ */
+
+
+
+
+
+
+
+
diff --git a/drivers/mtk_wcn_combo/common/core/include/wmt_dbg.h b/drivers/mtk_wcn_combo/common/core/include/wmt_dbg.h
new file mode 100755 (executable)
index 0000000..33fd494
--- /dev/null
@@ -0,0 +1,48 @@
+\r
+#ifndef _WMT_DBG_H_\r
+#define _WMT_DBG_H_\r
+#include "osal.h"\r
+\r
+#define STP_SDIO      0x04\r
+#define STP_UART_MAND 0x02\r
+#define STP_UART_FULL 0x01\r
+\r
+#define CFG_WMT_DBG_SUPPORT 1 // support wmt_dbg or not\r
+\r
+#if CFG_WMT_DBG_SUPPORT\r
+typedef struct _COEX_BUF{\r
+    UINT8 buffer[128];\r
+    INT32 availSize; \r
+}COEX_BUF, *P_COEX_BUF;\r
+\r
+typedef enum _ENUM_CMD_TYPE_T {\r
+    WMTDRV_CMD_ASSERT = 0,\r
+    WMTDRV_CMD_EXCEPTION = 1,\r
+    WMTDRV_CMD_COEXDBG_00 = 2,\r
+    WMTDRV_CMD_COEXDBG_01 = 3,\r
+    WMTDRV_CMD_COEXDBG_02 = 4,\r
+    WMTDRV_CMD_COEXDBG_03 = 5,\r
+    WMTDRV_CMD_COEXDBG_04 = 6,\r
+    WMTDRV_CMD_COEXDBG_05 = 7,\r
+    WMTDRV_CMD_COEXDBG_06 = 8,\r
+    WMTDRV_CMD_COEXDBG_07 = 9,\r
+    WMTDRV_CMD_COEXDBG_08 = 10,\r
+    WMTDRV_CMD_COEXDBG_09 = 11,\r
+    WMTDRV_CMD_COEXDBG_10 = 12,\r
+    WMTDRV_CMD_COEXDBG_11 = 13,\r
+    WMTDRV_CMD_COEXDBG_12 = 14,\r
+    WMTDRV_CMD_COEXDBG_13 = 15,\r
+    WMTDRV_CMD_COEXDBG_14 = 16,\r
+    WMTDRV_CMD_COEXDBG_15 = 17,    \r
+    WMTDRV_CMD_MAX\r
+} ENUM_WMTDRV_CMD_T, *P_ENUM_WMTDRV_CMD_T;\r
+\r
+\r
+typedef INT32 (*WMT_DEV_DBG_FUNC)(INT32 par1, INT32 par2, INT32 par3);\r
+INT32 wmt_dev_dbg_setup(VOID);\r
+INT32 wmt_dev_dbg_remove(VOID);\r
+\r
+\r
+#endif\r
+\r
+#endif\r
diff --git a/drivers/mtk_wcn_combo/common/core/include/wmt_func.h b/drivers/mtk_wcn_combo/common/core/include/wmt_func.h
new file mode 100755 (executable)
index 0000000..a04bcda
--- /dev/null
@@ -0,0 +1,134 @@
+/*! \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
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+*                           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/mtk_wcn_combo/common/core/include/wmt_ic.h b/drivers/mtk_wcn_combo/common/core/include/wmt_ic.h
new file mode 100755 (executable)
index 0000000..1f857c4
--- /dev/null
@@ -0,0 +1,113 @@
+/*! \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_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_VER_E7 "E7"
+
+#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/mtk_wcn_combo/common/core/include/wmt_lib.h b/drivers/mtk_wcn_combo/common/core/include/wmt_lib.h
new file mode 100755 (executable)
index 0000000..c40349a
--- /dev/null
@@ -0,0 +1,327 @@
+/*! \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 <mach/mtk_wcn_cmb_stub.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 WMT_OP_BUF_SIZE (16)
+#if 0 /* moved to wmt_exp.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
+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 2000/*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 5500
+
+#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
+********************************************************************************
+*/
+#if 0 /* moved to wmt_exp.h */
+/* FIXME: apply KERN_* definition? */
+extern UINT32 gWmtDbgLvl ;
+#ifndef DFT_TAG
+#define DFT_TAG         "[WMT-DFT]"
+#endif
+
+#define WMT_LOUD_FUNC(fmt, arg...)   if (gWmtDbgLvl >= WMT_LOG_LOUD) { osal_dbg_print(DFT_TAG "[L]%s:"  fmt, __FUNCTION__ ,##arg);}
+#define WMT_INFO_FUNC(fmt, arg...)   if (gWmtDbgLvl >= WMT_LOG_INFO) { osal_info_print(DFT_TAG "[I]%s:"  fmt, __FUNCTION__ ,##arg);}
+#define WMT_WARN_FUNC(fmt, arg...)   if (gWmtDbgLvl >= WMT_LOG_WARN) { osal_warn_print(DFT_TAG "[W]%s:"  fmt, __FUNCTION__ ,##arg);}
+#define WMT_ERR_FUNC(fmt, arg...)    if (gWmtDbgLvl >= WMT_LOG_ERR) { osal_err_print(DFT_TAG "[E]%s(%d):"  fmt, __FUNCTION__ , __LINE__, ##arg);}
+#define WMT_DBG_FUNC(fmt, arg...)    if (gWmtDbgLvl >= WMT_LOG_DBG) { osal_dbg_print(DFT_TAG "[D]%s:"  fmt, __FUNCTION__ ,##arg);}
+#define WMT_TRC_FUNC(f)              if (gWmtDbgLvl >= WMT_LOG_DBG) { osal_dbg_print(DFT_TAG "<%s> <%d>\n", __FUNCTION__, __LINE__);}
+#endif
+
+/*******************************************************************************
+*                              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_SDIO1_ON = 7, /* is SDIO1 on */
+    WMT_STAT_SDIO2_ON = 8, /* is SDIO2 on */
+    WMT_STAT_SDIO_WIFI_ON = 9,  /* is Wi-Fi SDIO function on */
+    WMT_STAT_SDIO_STP_ON = 10,  /* is STP SDIO function on */
+    WMT_STAT_RST_ON = 11,
+    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;
+       UCHAR addRess[4];
+       UCHAR patchName[256];
+}WMT_PATCH_INFO,*P_WMT_PATCH_INFO;
+
+
+/* OS independent wrapper for WMT_OP */
+typedef struct _DEV_WMT_ {
+
+    OSAL_SLEEPABLE_LOCK psm_lock;        
+    /* WMTd thread information */
+//    struct task_struct *pWmtd;   /* main thread (wmtd) handle */
+    OSAL_THREAD thread;
+//    wait_queue_head_t rWmtdWq;  /*WMTd command wait queue */
+    OSAL_EVENT rWmtdWq;    //rename
+    //ULONG state; /* bit field of WMT_STAT */
+    OSAL_BIT_OP_VAR state;
+
+    /* STP context information */
+//    wait_queue_head_t rWmtRxWq;  /* STP Rx wait queue */
+    OSAL_EVENT rWmtRxWq; //rename
+//    WMT_STP_FUNC rStpFunc; /* STP functions */
+    WMT_FDRV_CB  rFdrvCb;
+
+    /* WMT Configurations */
+    WMT_HIF_CONF  rWmtHifConf;
+    WMT_GEN_CONF  rWmtGenConf;
+
+    /* Patch information */
+    UCHAR cPatchName[NAME_MAX + 1];
+    UCHAR cFullPatchName[NAME_MAX + 1];
+       UINT32 patchNum;
+    const osal_firmware *pPatch;
+
+    UCHAR cWmtcfgName[NAME_MAX + 1];
+    const osal_firmware *pWmtCfg;
+
+       const osal_firmware *pNvram;
+       
+    /* Current used UART port description*/
+    CHAR 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 */
+    UCHAR cCmd[NAME_MAX + 1];
+    INT32 cmdResult;
+//    struct completion cmd_comp;
+//    wait_queue_head_t cmd_wq; /* read command queues */
+    OSAL_SIGNAL cmdResp;
+    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
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                           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 (UINT8 *data, UINT32 size, UINT32 *writtenSize);
+extern INT32 wmt_lib_tx_raw (UINT8 *data, UINT32 size, UINT32 *writtenSize);
+extern INT32 wmt_lib_rx(UINT8 *buff, UINT32 buffLen, UINT32 *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 UCHAR *wmt_lib_get_cmd(VOID);
+extern P_OSAL_EVENT wmt_lib_get_cmd_event(VOID);
+extern INT32 wmt_lib_set_patch_name(UCHAR *cPatchName);
+extern INT32 wmt_lib_set_uart_name(CHAR *cUartName);
+extern INT32 wmt_lib_set_hif(ULONG 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
+    );
+INT32 wmt_lib_sdio_ctrl(UINT32 on);
+
+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 INT32 wmt_lib_set_stp_wmt_last_close(UINT32 value);
+
+extern VOID wmt_lib_set_patch_num(ULONG 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 INT32 wmt_lib_merge_if_flag_ctrl(UINT32 enable);
+extern INT32 wmt_lib_merge_if_flag_get(UINT32 enable);
+
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+
+#endif /* _WMT_LIB_H_ */
+
diff --git a/drivers/mtk_wcn_combo/common/core/psm_core.c b/drivers/mtk_wcn_combo/common/core/psm_core.c
new file mode 100755 (executable)
index 0000000..38165f0
--- /dev/null
@@ -0,0 +1,2005 @@
+#include "osal_typedef.h"
+#include "osal.h"
+#include "psm_core.h"
+#include "stp_core.h"
+#include <mach/mtk_wcn_cmb_stub.h>
+
+INT32         gPsmDbgLevel = STP_PSM_LOG_INFO;
+MTKSTP_PSM_T  stp_psm_i;
+MTKSTP_PSM_T  *stp_psm = &stp_psm_i; 
+
+#define STP_PSM_LOUD_FUNC(fmt, arg...)   if(gPsmDbgLevel >= STP_PSM_LOG_LOUD){ osal_dbg_print(PFX_PSM "%s: "  fmt, __FUNCTION__ ,##arg);}
+#define STP_PSM_DBG_FUNC(fmt, arg...)    if(gPsmDbgLevel >= STP_PSM_LOG_DBG){  osal_dbg_print(PFX_PSM "%s: "  fmt, __FUNCTION__ ,##arg);}
+#define STP_PSM_INFO_FUNC(fmt, arg...)   if(gPsmDbgLevel >= STP_PSM_LOG_INFO){ osal_dbg_print(PFX_PSM "[I]%s: "  fmt, __FUNCTION__ ,##arg);}
+#define STP_PSM_WARN_FUNC(fmt, arg...)   if(gPsmDbgLevel >= STP_PSM_LOG_WARN){ osal_dbg_print(PFX_PSM "[W]%s: "  fmt, __FUNCTION__ ,##arg);}
+#define STP_PSM_ERR_FUNC(fmt, arg...)    if(gPsmDbgLevel >= STP_PSM_LOG_ERR){  osal_dbg_print(PFX_PSM "[E]%s(%d):ERROR! "   fmt, __FUNCTION__ , __LINE__, ##arg);}
+#define STP_PSM_TRC_FUNC(f)              if(gPsmDbgLevel >= STP_PSM_LOG_DBG){  osal_dbg_print(PFX_PSM "<%s> <%d>\n", __FUNCTION__, __LINE__);}
+
+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 const PCHAR g_psm_state[STP_PSM_MAX_STATE] = {
+    "ACT",
+    "ACT_INACT",
+    "INACT",
+    "INACT_ACT"
+};
+
+static const PCHAR g_psm_action[STP_PSM_MAX_ACTION] = {
+    "SLEEP" ,
+    "HOST_AWAKE",
+    "WAKEUP",
+    "EIRQ",
+    "ROLL_BACK"
+};
+
+static const PCHAR 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"
+};
+
+INT32 _stp_psm_release_data(MTKSTP_PSM_T *stp_psm);
+
+static inline INT32  _stp_psm_get_state(MTKSTP_PSM_T *stp_psm);
+
+static INT32 _stp_psm_is_redundant_active_op(
+    P_OSAL_OP pOp,
+    P_OSAL_OP_Q pOpQ
+);
+
+static INT32 _stp_psm_clean_up_redundant_active_op(
+        P_OSAL_OP_Q pOpQ
+    );
+static MTK_WCN_BOOL _stp_psm_is_quick_ps_support (VOID);
+extern void mt_combo_plt_enter_deep_idle (
+    COMBO_IF src
+    ) ;
+
+extern void mt_combo_plt_exit_deep_idle (
+    COMBO_IF src
+    ) ;
+MTK_WCN_BOOL mtk_wcn_stp_psm_dbg_level(UINT32 dbglevel)
+{
+   if (0 <= dbglevel && dbglevel <= 4)
+   {
+      gPsmDbgLevel = dbglevel;
+      STP_PSM_INFO_FUNC("gPsmDbgLevel = %d\n", gPsmDbgLevel);
+      return true;
+   }
+   else
+   {
+      STP_PSM_INFO_FUNC("invalid psm debug level. gPsmDbgLevel = %d\n", gPsmDbgLevel);
+   }
+   return false;
+}
+
+/* change from macro to static function to enforce type checking on parameters. */
+static INT32 psm_fifo_lock_init (MTKSTP_PSM_T *psm)
+{
+       
+
+#if CFG_PSM_CORE_FIFO_SPIN_LOCK
+       #if defined(CONFIG_PROVE_LOCKING)
+               osal_unsleepable_lock_init(&(psm->hold_fifo_lock));
+               return 0;
+       #else
+       return osal_unsleepable_lock_init(&(psm->hold_fifo_lock));
+       #endif
+#else
+#if defined(CONFIG_PROVE_LOCKING)
+       osal_sleepable_lock_init(&(psm->hold_fifo_lock));
+       return 0;
+#else
+    return osal_sleepable_lock_init(&(psm->hold_fifo_lock));
+#endif
+#endif
+}
+
+static INT32 psm_fifo_lock_deinit (MTKSTP_PSM_T *psm)
+{
+#if CFG_PSM_CORE_FIFO_SPIN_LOCK
+    return osal_unsleepable_lock_deinit(&(psm->hold_fifo_lock));
+#else
+    return osal_sleepable_lock_deinit(&(psm->hold_fifo_lock));
+#endif
+}
+
+static INT32 psm_fifo_lock (MTKSTP_PSM_T *psm)
+{
+       
+
+#if CFG_PSM_CORE_FIFO_SPIN_LOCK
+    return osal_lock_unsleepable_lock(&(psm->hold_fifo_lock));
+#else
+    return osal_lock_sleepable_lock(&(psm->hold_fifo_lock));
+#endif
+}
+
+static INT32 psm_fifo_unlock (MTKSTP_PSM_T *psm)
+{
+       
+
+#if CFG_PSM_CORE_FIFO_SPIN_LOCK
+    return osal_unlock_unsleepable_lock(&(psm->hold_fifo_lock));
+#else
+    return osal_unlock_sleepable_lock(&(psm->hold_fifo_lock));
+#endif
+}
+
+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;//*(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("Unkown 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 INT32 _stp_psm_is_redundant_active_op(
+    P_OSAL_OP pOp,
+    P_OSAL_OP_Q pOpQ
+)
+{
+    UINT32 opId = 0;
+    UINT32 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 INT32 _stp_psm_clean_up_redundant_active_op(
+        P_OSAL_OP_Q pOpQ
+    )
+{
+    UINT32 prev_opId = 0;
+    UINT32 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));
+
+    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;
+        }
+
+        /* 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(stp_psm->flag & STP_PSM_RESET_EN)
+        {
+            stp_psm->flag &= ~STP_PSM_RESET_EN;
+        }
+
+        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("<psm time>>>>");
+    }
+    
+    return 0;
+}
+
+static inline INT32  _stp_psm_get_state(MTKSTP_PSM_T *stp_psm)
+{
+
+    if(stp_psm == NULL)
+    {
+        return STP_PSM_OPERATION_FAIL;
+    }
+    else 
+    {
+        if(stp_psm->work_state < STP_PSM_MAX_STATE)
+        {
+            return stp_psm->work_state;
+        } 
+        else 
+        {
+            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;
+    }
+    else 
+    {
+         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);
+                stp_psm->flag |= STP_PSM_BLOCK_DATA_EN;
+//                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((stp_psm->flag & STP_PSM_WMT_EVENT_DISABLE_MONITOR)!= 0)
+     {
+        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;
+    }
+    else 
+    {
+        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;
+    }
+    else 
+    {
+        psm_fifo_lock(stp_psm);
+        
+        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,(UINT8 *) &type , sizeof(UINT8));
+        //lenght
+        osal_fifo_in(&stp_psm->hold_fifo,(UINT8 *) &len , sizeof(UINT32));
+        //buffer
+        osal_fifo_in(&stp_psm->hold_fifo,(UINT8 *) buffer, len);
+        //delimiter
+        osal_fifo_in(&stp_psm->hold_fifo,(UINT8 *) delimiter, 2);
+
+        psm_fifo_unlock(stp_psm);
+        
+        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
+        psm_fifo_lock(stp_psm);
+
+        ret = osal_fifo_out(&stp_psm->hold_fifo, (UINT8 *)&type, sizeof(UINT8));
+        ret = osal_fifo_out(&stp_psm->hold_fifo, (UINT8 *)&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, (UINT8 *)stp_psm->out_buf, len);
+        }
+        
+        ret = osal_fifo_out(&stp_psm->hold_fifo, (UINT8 *)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--;
+        psm_fifo_unlock(stp_psm);
+    }
+    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;
+    }
+    else 
+    {
+        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(%d) 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);
+    }
+    else 
+    {
+        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(%d) 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;
+    }
+    else 
+    {
+        if((stp_psm->flag & STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY) != 0)
+        {
+            return 0;
+        }
+
+        if((stp_psm->flag & STP_PSM_WMT_EVENT_DISABLE_MONITOR_RX_HIGH_DENSITY) != 0)
+        {
+            return 0;
+        }
+
+        if((stp_psm->flag & STP_PSM_WMT_EVENT_DISABLE_MONITOR) != 0)
+        {
+            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(%d) bRet(%d) \n\n",
+            pOp->op.opId,
+            pOp->op.au4OpData[0],
+            bRet);
+
+        retval = (0 == bRet) ? (STP_PSM_OPERATION_FAIL) : 0;
+    }
+    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;
+    INT32 ret = 0;
+
+    STP_PSM_DBG_FUNC("PSM MODE RESET=============================>\n\r");
+        
+    STP_PSM_INFO_FUNC("_stp_psm_reset\n");
+    STP_PSM_INFO_FUNC("reset-wake_lock(%d)\n", osal_wake_lock_count(&stp_psm->wake_lock));
+    osal_wake_unlock(&stp_psm->wake_lock);
+    STP_PSM_INFO_FUNC("reset-wake_lock(%d)\n", osal_wake_lock_count(&stp_psm->wake_lock));
+
+    //--> serialized the request from wmt <--//
+    ret = osal_lock_sleepable_lock(&stp_psm->user_lock);
+    if (ret) {
+        STP_PSM_ERR_FUNC("--->lock stp_psm->user_lock failed, ret=%d\n", ret);
+        return ret;
+    }
+
+    //--> disable psm <--//
+    stp_psm->flag = STP_PSM_WMT_EVENT_DISABLE_MONITOR;
+    _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);
+
+    psm_fifo_lock(stp_psm);
+    osal_fifo_reset(&stp_psm->hold_fifo);
+    psm_fifo_unlock(stp_psm);
+
+    //--> stop psm thread wait <--//
+    stp_psm->flag |= STP_PSM_RESET_EN;
+    osal_trigger_event(&stp_psm->wait_wmt_q);
+
+    osal_unlock_sleepable_lock(&stp_psm->user_lock);
+
+    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=0x%08x\n", __func__, stp_psm->flag);
+    
+    return ((stp_psm->flag & STP_PSM_WMT_EVENT_SLEEP_EN) || 
+        (stp_psm->flag & STP_PSM_WMT_EVENT_WAKEUP_EN) ||
+        (stp_psm->flag & STP_PSM_WMT_EVENT_ROLL_BACK_EN) ||
+        (stp_psm->flag & STP_PSM_RESET_EN));
+}
+
+
+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;
+    }
+    else 
+    {
+        osal_wait_for_event_timeout(&stp_psm->wait_wmt_q,
+             _stp_psm_wait_wmt_event,
+             (void *)stp_psm);
+
+        if(stp_psm->flag & STP_PSM_WMT_EVENT_WAKEUP_EN)
+        {
+            stp_psm->flag &= ~STP_PSM_WMT_EVENT_WAKEUP_EN;
+//            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.            
+            stp_psm->flag &= ~STP_PSM_BLOCK_DATA_EN;
+            //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 ( stp_psm->flag & STP_PSM_WMT_EVENT_SLEEP_EN) 
+        {
+            stp_psm->flag &= ~STP_PSM_WMT_EVENT_SLEEP_EN;
+            _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_UART);
+            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 ( stp_psm->flag & STP_PSM_WMT_EVENT_ROLL_BACK_EN) 
+        {
+            stp_psm->flag &= ~STP_PSM_WMT_EVENT_ROLL_BACK_EN;
+            if(_stp_psm_get_state(stp_psm) == ACT_INACT){
+//                osal_lock_unsleepable_lock(&stp_psm->flagSpinlock);
+                _stp_psm_release_data(stp_psm);
+                stp_psm->flag &= ~STP_PSM_BLOCK_DATA_EN;
+                _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 (stp_psm->flag & STP_PSM_RESET_EN)
+        {
+            stp_psm->flag &= ~STP_PSM_WMT_EVENT_ROLL_BACK_EN;
+        }
+        else 
+        {
+            STP_PSM_ERR_FUNC("flag = %x<== Abnormal flag be set!!\n\r", stp_psm->flag);
+            STP_PSM_ERR_FUNC("state = %d, flag = %d\n", stp_psm->work_state, stp_psm->flag);
+        }
+        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]);
+                stp_psm->flag &= ~STP_PSM_WMT_EVENT_WAKEUP_EN;
+                stp_psm->flag |= STP_PSM_WMT_EVENT_SLEEP_EN;
+
+                //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;
+                stp_psm->flag |=  STP_PSM_WMT_EVENT_ROLL_BACK_EN;
+                //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 = %d\n", stp_psm->work_state, stp_psm->flag);
+                }
+                else 
+                {
+                    STP_PSM_ERR_FUNC("Invalid Action!!\n\r");
+                }
+                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]);
+                stp_psm->flag &= ~STP_PSM_WMT_EVENT_SLEEP_EN;
+                stp_psm->flag |= STP_PSM_WMT_EVENT_WAKEUP_EN;
+                //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]);
+                stp_psm->flag &= ~STP_PSM_WMT_EVENT_SLEEP_EN;
+                stp_psm->flag |= STP_PSM_WMT_EVENT_WAKEUP_EN;
+                //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]);
+               // stp_psm->flag &= ~STP_PSM_WMT_EVENT_ROLL_BACK_EN;
+                stp_psm->flag |=  STP_PSM_WMT_EVENT_ROLL_BACK_EN;
+                //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 = %d\n", stp_psm->work_state, stp_psm->flag);
+                }
+                else 
+                {
+                    STP_PSM_ERR_FUNC("Invalid Action!!\n\r");
+                }
+                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 = %d\n", stp_psm->work_state, stp_psm->flag);
+            }
+            else 
+            {
+                STP_PSM_ERR_FUNC("Invalid Action!!\n\r");
+            }
+
+            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 = %d\n", stp_psm->work_state, stp_psm->flag);
+            }
+            else 
+            {
+                STP_PSM_ERR_FUNC("Invalid Action!!\n\r");
+            }
+
+            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 = %d\n", stp_psm->work_state, stp_psm->flag);
+            }
+            else 
+            {
+                STP_PSM_ERR_FUNC("Invalid Action!!\n\r");
+            }
+
+            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 (stp_psm->flag & STP_PSM_WMT_EVENT_DISABLE_MONITOR) {
+                    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 = %d\n", stp_psm->work_state, stp_psm->flag);
+
+                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_UART);
+                    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_UART);
+                    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 = %d\n", stp_psm->work_state, stp_psm->flag);
+                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 = %d\n", stp_psm->work_state, stp_psm->flag);
+            ret = STP_PSM_OPERATION_FAIL;
+
+            break;
+    }
+    return ret;
+}
+
+static inline void _stp_psm_stp_is_idle(ULONG data)
+{
+     MTKSTP_PSM_T *stp_psm = (MTKSTP_PSM_T *)data;
+
+     stp_psm->flag &= ~STP_PSM_WMT_EVENT_DISABLE_MONITOR_RX_HIGH_DENSITY;
+     stp_psm->flag &= ~STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY;
+
+     if((stp_psm->flag & STP_PSM_WMT_EVENT_DISABLE_MONITOR)!= 0)
+     {
+        STP_PSM_DBG_FUNC("STP-PSM DISABLE!\n");
+        return ;
+     }
+
+     STP_PSM_INFO_FUNC("**IDLE is over %d msec, go to sleep!!!**\n", stp_psm->idle_time_to_sleep);
+     _stp_psm_notify_wmt_sleep_wq(stp_psm);
+}
+
+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 = (UINT32)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;
+     }
+     else 
+     {
+        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(stp_psm->flag & STP_PSM_BLOCK_DATA_EN)
+    {
+        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(stp_psm->flag & STP_PSM_WMT_EVENT_DISABLE_MONITOR)
+    {
+        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_msleep(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);
+        return STP_PSM_OPERATION_FAIL;
+     }   
+     else
+     {
+        STP_PSM_DBG_FUNC("+Total waits for %s takes %d msec\n", g_psm_state[state], i*POLL_WAIT);
+        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");
+    
+    ret = osal_lock_sleepable_lock(&stp_psm->user_lock);
+    if (ret) {
+        STP_PSM_ERR_FUNC("--->lock stp_psm->user_lock failed, ret=%d\n", ret);
+        return ret;
+    }
+    
+    stp_psm->flag |= STP_PSM_WMT_EVENT_DISABLE_MONITOR;   
+    ret = _stp_psm_do_wakeup(stp_psm);
+    osal_unlock_sleepable_lock(&stp_psm->user_lock); 
+    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");
+    
+    ret = osal_lock_sleepable_lock(&stp_psm->user_lock);
+    if (ret) {
+        STP_PSM_ERR_FUNC("--->lock stp_psm->user_lock failed, ret=%d\n", ret);
+        return ret;
+    }
+    
+    stp_psm->flag |= STP_PSM_WMT_EVENT_DISABLE_MONITOR;
+    
+    ret = _stp_psm_do_wakeup(stp_psm);
+    if(ret == STP_PSM_OPERATION_SUCCESS)
+    {
+        stp_psm->flag &= ~STP_PSM_WMT_EVENT_DISABLE_MONITOR;
+        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");
+    }
+    osal_unlock_sleepable_lock(&stp_psm->user_lock);
+    
+    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();
+}
+
+INT32 stp_psm_disable_by_tx_rx_density(MTKSTP_PSM_T *stp_psm, INT32 dir){
+
+    //easy the variable maintain beween stp tx, rx thread.
+    //so we create variable for tx, rx respectively.
+    
+    static INT32 tx_cnt = 0;
+    static INT32 rx_cnt = 0;
+    static INT32 is_tx_first = 1;
+    static INT32 is_rx_first = 1;
+    static ULONG tx_end_time = 0;
+    static ULONG rx_end_time = 0;
+    
+    //
+    //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)
+            {
+                stp_psm->flag |= STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY;
+                stp_psm_start_monitor(stp_psm);
+            }
+            else 
+            {
+                stp_psm->flag &= ~STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY;
+            }
+            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.
+            {
+                stp_psm->flag |= STP_PSM_WMT_EVENT_DISABLE_MONITOR_RX_HIGH_DENSITY;
+                stp_psm_start_monitor(stp_psm);
+            }
+            else 
+            {
+                stp_psm->flag &= ~STP_PSM_WMT_EVENT_DISABLE_MONITOR_RX_HIGH_DENSITY;
+            }
+            rx_cnt = 0;
+            if(is_rx_first)
+                is_rx_first = 0;
+        }  
+    }
+
+    return 0;
+}
+
+/*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);
+}
+
+INT32 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;
+}
+
+
+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 = 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->user_lock);
+    psm_fifo_lock_init(stp_psm);
+    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);
+
+
+    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(!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_fifo_deinit(&stp_psm->hold_fifo);
+    osal_sleepable_lock_deinit(&stp_psm->user_lock);
+    psm_fifo_lock_deinit(stp_psm);
+    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;
+}
+
+EXPORT_SYMBOL(mtk_wcn_stp_psm_dbg_level);
+
diff --git a/drivers/mtk_wcn_combo/common/core/stp_core.c b/drivers/mtk_wcn_combo/common/core/stp_core.c
new file mode 100755 (executable)
index 0000000..50dc66d
--- /dev/null
@@ -0,0 +1,3254 @@
+
+#include "stp_core.h"
+#include "psm_core.h"
+#include "btm_core.h"
+#include "stp_dbg.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;
+
+#define REMOVE_USELESS_LOG 1
+
+
+/* global variables */
+static const UINT8       stp_delimiter[STP_DEL_SIZE] = {0x55, 0x55};
+static INT32             fgEnableNak         = 0; // 0=enable NAK; 1=disable NAK
+static INT32             fgEnableDelimiter   = 0; // 0=disable Delimiter; 1=enable Delimiter
+
+/* common interface */
+static IF_TX            sys_if_tx           = NULL;
+/* event/signal */
+static EVENT_SET        sys_event_set = NULL;
+static EVENT_TX_RESUME  sys_event_tx_resume = NULL;
+static FUNCTION_STATUS  sys_check_function_status = NULL;
+/* kernel lib */
+//INT32                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))
+
+
+/*[PatchNeed]Need to calulate 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 = NULL;
+#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(ULONG data);
+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);
+INT32 stp_send_data_no_ps(UINT8 *buffer, UINT32 length, UINT8 type);
+static INT32  stp_process_rxack(VOID);
+static VOID   stp_process_packet(VOID);
+VOID stp_do_tx_timeout(VOID);
+
+/*Bad*/
+extern INT32 mtk_wcn_sys_if_rx(UINT8 *data, INT32 size);
+#if WMT_PLAT_ALPS
+extern void stop_log(void);//uart export API
+#endif
+
+static INT32 stp_ctx_lock_init (mtkstp_context_struct *pctx)
+{
+#if CFG_STP_CORE_CTX_SPIN_LOCK
+       #if defined(CONFIG_PROVE_LOCKING)
+           osal_unsleepable_lock_init(&((pctx)->stp_mutex));
+               return 0;
+       #else
+               return osal_unsleepable_lock_init(&((pctx)->stp_mutex));
+       #endif
+#else
+       #if defined(CONFIG_PROVE_LOCKING)
+               osal_sleepable_lock_init(&((pctx)->stp_mutex));
+               return 0;
+       #else
+           return osal_sleepable_lock_init(&((pctx)->stp_mutex));
+       #endif
+#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)
+{
+       //dump_stack();
+       //printk("stp_lock\n\r");
+#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)
+{
+       //dump_stack();
+       //printk("stp_unlock\n\r");
+
+#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 (0 <= dbglevel && dbglevel <= 4)
+    {
+     gStpDbgLvl = dbglevel;
+     STP_INFO_FUNC("gStpDbgLvl = %d\n", gStpDbgLvl);
+     return MTK_WCN_BOOL_TRUE;
+    }
+    else
+    {
+     STP_INFO_FUNC("invalid stp debug level. gStpDbgLvl = %d\n", gStpDbgLvl);
+    }
+    return MTK_WCN_BOOL_FALSE;
+}
+#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;
+    }
+    else
+    {
+        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;
+
+    return;
+}
+
+/*****************************************************************************
+* 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;
+
+    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;
+
+    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;
+
+    return;
+}
+
+//static void stp_tx_timeout_handler(void){
+static void stp_tx_timeout_handler(ULONG data)
+{
+    STP_WARN_FUNC("call retry btm retry wq ...\n");
+    /*shorten the softirq lattency*/
+       #if WMT_PLAT_ALPS
+    stop_log();
+       #endif
+    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;
+    UINT8 resync[4];
+       
+       STP_WARN_FUNC("==============================================================================\n");
+
+    stp_ctx_lock(&stp_core_ctx);
+
+    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 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)
+        {
+            osal_timer_stop(&stp_core_ctx.tx_timer);
+            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);
+            // stop_log();
+            mtk_wcn_stp_dbg_dump_package();                            
+            stp_notify_btm_dump(STP_BTM_CORE(stp_core_ctx));
+
+            /*Whole Chip Reset Procedure Invoke*/
+            /*if(STP_NOT_ENABLE_DBG(stp_core_ctx))*/
+            {
+                osal_dbg_assert_aee("[MT662x]NoAck", "**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");
+                }
+            }
+        }
+    }
+
+    stp_ctx_unlock(&stp_core_ctx);
+       STP_WARN_FUNC("==============================================================================#\n");
+    return;
+}
+
+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;
+    }
+    else
+    {
+        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;
+    }
+}
+/*****************************************************************************
+* 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;
+}
+
+/*****************************************************************************
+* FUNCTION
+*  tx_queue_room_available
+* DESCRIPTION
+*  check room if availabe,
+* 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 availale 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", __FUNCTION__);
+        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 availale 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;
+    }
+
+    return;
+}
+
+/*****************************************************************************
+* 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;
+
+    stp_ctx_lock(&stp_core_ctx);
+
+    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)
+    {
+        stp_ctx_unlock(&stp_core_ctx);
+        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;
+    }
+
+    stp_ctx_unlock(&stp_core_ctx);
+
+    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);
+        }
+    }
+
+    return;
+}
+
+
+/*****************************************************************************
+* 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)(&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);
+    }
+
+    return;
+}
+
+
+
+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;
+
+    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
+    }
+    else if (STP_NOT_ENABLE(stp_core_ctx) && WMT_TASK_INDX == type)
+    {
+        //ret = mtk_wcn_stp_send_data_raw(buffer, length, type);
+    }
+
+    // STP over SDIO
+    else if ((mtk_wcn_stp_is_sdio_mode() || mtk_wcn_stp_is_uart_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 UART
+    else if ( mtk_wcn_stp_is_uart_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", __FUNCTION__);
+            ret = 0;
+        }
+    }
+
+    stp_ctx_unlock(&stp_core_ctx);
+
+    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 = 0;
+    MTK_WCN_BOOL b;
+    MTK_WCN_BOOL is_function_active = 0;
+    static INT32 stp_process_packet_fail_count = 0;
+        
+    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");
+            }
+
+            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);
+
+            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)            
+            {                
+                const static 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 <--");                
+                }            
+            }
+        
+            
+
+            fgRxOk = stp_add_to_rx_queue(stp_core_ctx.rx_buf, stp_core_ctx.rx_counter, stp_core_ctx.parser.type);
+        }
+        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*/
+            }
+        }
+
+        /* enqueue successfully */
+        if(fgRxOk == 0)
+        {
+            stp_process_packet_fail_count = 0;
+            /*notify corresponding subfunction of incoming data*/
+            (*sys_event_set)(stp_core_ctx.parser.type);
+
+            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);
+        }
+        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);
+        txAck = stp_core_ctx.sequence.txack;
+        stp_send_ack(txAck, 1);
+        stp_ctx_unlock(&stp_core_ctx);
+               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*/
+        (*sys_event_tx_resume)(stp_core_ctx.sequence.winspace); // notify adaptation layer for possible tx resume mechanism
+    }
+
+    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");
+               #if WMT_PLAT_ALPS
+        stop_log();                     //dump_uart_history();
+        #endif
+        mtk_wcn_stp_dbg_dump_package();                     
+        stp_notify_btm_dump(STP_BTM_CORE(stp_core_ctx));
+
+        /*Whole Chip Reset Procedure Invoke*/
+        /*if(STP_NOT_ENABLE_DBG(stp_core_ctx))*/
+        {
+            //(*sys_dbg_assert_aee)("[MT662x]Ack Miss", "**STP Ack Miss**\n Ack Miss.\n");
+            osal_dbg_assert_aee("[MT662x]Ack Miss", "**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");
+            }
+        }
+    }
+
+    return;
+}
+
+/*****************************************************************************
+* 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;
+
+    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);
+
+    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)
+{
+
+    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));
+    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
+*****************************************************************************/
+
+INT32 mtk_wcn_stp_btm_get_dmp(CHAR *buf, INT32 *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
+*****************************************************************************/
+INT32 mtk_wcn_stp_psm_notify_stp(const MTKSTP_PSM_ACTION_T action){
+    return stp_psm_notify_stp(STP_PSM_CORE(stp_core_ctx), action);
+}
+
+INT32 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);
+           }
+           else
+           {
+               STP_WARN_FUNC("STP Not Ready, Dont do Sleep/Wakeup\n");
+               return -1;
+           }
+    }
+    else
+    {
+           if( mtk_wcn_stp_is_ready() && mtk_wcn_stp_is_uart_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;
+           }
+           else
+           {
+               STP_WARN_FUNC("STP Not Ready, Dont do Sleep/Wakeup\n");
+               return -1;
+           }   
+    }
+#else
+    if( mtk_wcn_stp_is_ready() && mtk_wcn_stp_is_uart_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;
+       }
+       else
+       {
+           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));
+           }
+           else
+           {
+               STP_WARN_FUNC("STP Not Ready, Dont do Sleep/Wakeup\n");
+               return -1;
+           }
+    }
+    else
+    {
+           if( mtk_wcn_stp_is_ready() && mtk_wcn_stp_is_uart_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;
+           }
+           else
+           {
+               STP_WARN_FUNC("STP Not Ready, Dont do Sleep/Wakeup\n");
+               return -1;
+           }
+    }
+#else
+    if( mtk_wcn_stp_is_ready() && mtk_wcn_stp_is_uart_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;
+    }
+    else
+    {
+        STP_WARN_FUNC("STP Not Ready, Dont do Sleep/Wakeup\n");
+        return -1;
+    }
+#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_INFO_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_INFO_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("%s coredump function.\n", 0 == on ? "disable" : "enable")
+    return 0;
+}
+
+INT32 mtk_wcn_stp_coredump_flag_get(VOID)
+{
+    return STP_ENABLE_FW_COREDUMP_FLAG(stp_core_ctx);
+}
+
+
+
+
+
+
+
+
+/*****************************************************************************
+* 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
+*  INT32            0 = sucess; -1 = crc/checksum error
+*****************************************************************************/
+INT32 mtk_wcn_stp_parser_data(UINT8 *buffer, UINT32 length)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    INT32 i;
+    UINT8 *p_data;
+    UINT8 padding_len = 0;
+    INT32 remain_length; // GeorgeKuo: sync from MAUI, change to unsigned
+    MTK_WCN_BOOL is_function_active = 0;
+#ifdef DEBUG_DUMP_PACKET_HEAD
+    static UINT32 counter = 0;
+    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))
+    {
+        //(*sys_dbg_print)("mtk_wcn_stp_parser_data, buff = %x %x %x %x %x %x %x %x %x %x", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7], buffer[8], buffer[9]);
+        stp_add_to_rx_queue(buffer, length, STP_PENDING_TYPE(stp_core_ctx)); //route to task who send command
+
+        /* 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_uart_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);
+        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)
+                            if (gStpDbgLvl >= STP_LOG_DBG) {/*print header, when get the full STP header*/
+                                INT32 type = (*(p_data+1) & 0x70) >> 4;
+                                PCHAR type_name ="<UNKOWN>";
+
+                                //if(type == BT_TASK_INDX){
+                                    if(type == BT_TASK_INDX)
+                                        type_name="< BT>";
+                                    else if(type == GPS_TASK_INDX)
+                                        type_name="<GPS>";
+                                    else if(type == WMT_TASK_INDX)
+                                        type_name="<WMT>";
+                                    else if(type == FM_TASK_INDX)
+                                        type_name="< FM>";
+
+                                    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:
+
+                    /*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))
+                    {
+                        INT32 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))
+                        {
+                            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(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);
+                            osal_dbg_print("[len=%d][type=%d]\n%s\n",stp_core_ctx.rx_counter, stp_core_ctx.parser.type , stp_core_ctx.rx_buf);
+                            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);
+                        }
+                        
+                        /*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--;
+        }
+    }
+
+    // STP over UART
+    else if ( mtk_wcn_stp_is_uart_fullset_mode() && STP_IS_ENABLE(stp_core_ctx))
+    {
+        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)                            
+                            INT32 type = (*(p_data+1) & 0x70) >> 4;
+                            PCHAR type_name ="<UNKOWN>";
+                            if(type == BT_TASK_INDX)
+                                type_name="< BT>";
+                            else if(type == GPS_TASK_INDX)
+                                type_name="<GPS>";
+                            else if(type == WMT_TASK_INDX)
+                                type_name="<WMT>";
+                            else if(type == FM_TASK_INDX)
+                                type_name="< FM>";
+
+                            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);
+
+                            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();
+                                if(fgTriggerResume == 0)
+                                {
+                                    (*sys_event_tx_resume)(stp_core_ctx.sequence.winspace); // notify adaptation layer for possible tx resume mechanism
+                                }
+                            } else {
+                                STP_WARN_FUNC("Now it's inband reset process and drop ACK packet.\n");
+                            }
+                            stp_ctx_unlock(&stp_core_ctx);
+                            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 (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 (STP_IS_READY(stp_core_ctx)) {
+                                               #if WMT_PLAT_ALPS
+                           stop_log();
+                                               #endif
+                        mtk_wcn_stp_dbg_dump_package();
+                           stp_notify_btm_dump(STP_BTM_CORE(stp_core_ctx));
+                       }
+                       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 charactor(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) && (0 != mtk_wcn_stp_coredump_flag_get())){
+                            if (0 != stp_core_ctx.rx_counter)
+                            {
+                                STP_SET_READY(stp_core_ctx, 0);
+                                mtk_wcn_stp_coredump_start_ctrl(1);
+                                stp_psm_set_sleep_disable(stp_core_ctx.psm);
+                                stp_dbg_log_pkt(g_mtkstp_dbg, STP_DBG_FW_DMP/*STP_DBG_FW_ASSERT*/,STP_TASK_INDX,0,0,0,0,
+                                    (stp_core_ctx.rx_counter + 1),
+                                    stp_core_ctx.rx_buf);
+                            }
+                            osal_dbg_print("[len=%d][type=%d]\n%s\n",stp_core_ctx.rx_counter, stp_core_ctx.parser.type , stp_core_ctx.rx_buf);
+                            if (0 == osal_strncmp("coredump end", stp_core_ctx.rx_buf + stp_core_ctx.rx_counter - osal_strlen("coredump end") - 2, osal_strlen("coredump end")))
+                            {
+                                STP_ERR_FUNC("coredump end\n");
+                                mtk_wcn_stp_coredump_start_ctrl(0);
+                                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");
+                                }
+                            }
+                        }
+                        /*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();
+                            
+                            if (0 == mtk_wcn_stp_coredump_flag_get()) {
+                                STP_ERR_FUNC("fw error happend but coredump disabled\n");
+                            } else {
+                            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--;
+        }
+    }
+    /* 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 0;
+}
+
+/*****************************************************************************
+* 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_INFO_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())
+        {
+            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_INFO_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_INFO_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
+*****************************************************************************/
+INT32 mtk_wcn_stp_coredump_start_get(VOID)
+{
+    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
+*****************************************************************************/
+INT32 mtk_wcn_stp_send_data(const UINT8 *buffer, const UINT32 length, const UINT8 type)
+{
+    UINT8 mtkstp_header[MTKSTP_HEADER_SIZE], temp[2];
+    UINT8 *p_tx_buf = NULL;
+    UINT16 crc;
+    INT32 ret = 0;
+
+    //osal_buffer_dump(buffer,"tx", length, 32);
+
+    if (0 != STP_WMT_LAST_CLOSE(stp_core_ctx)) {
+        STP_ERR_FUNC("WMT lats close,shoud 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
+    if (MTK_WCN_BOOL_TRUE == stp_psm_is_quick_ps_support())
+    {
+           if(type != WMT_TASK_INDX)
+           {
+               stp_psm_disable_by_tx_rx_density(STP_PSM_CORE(stp_core_ctx), 0);
+           }
+
+           //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(stp_is_privileges_cmd(buffer, length , type))
+               {
+                   STP_DBG_FUNC("send privileges cmd\n");
+                   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\n", type, ret);
+                   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)    
+    {        
+        const static UINT8 rst_buf[4] = {0x01, 0x03, 0x0c, 0x00};        
+        if(!osal_strncmp(buffer, rst_buf, 4))        
+        {            
+            osal_printtimeofday("############ BT Rest start -->");        
+         }    
+    }
+
+    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
+    }
+    else if (STP_NOT_ENABLE(stp_core_ctx) && WMT_TASK_INDX == type)
+    {
+        //ret = mtk_wcn_stp_send_data_raw(buffer, length, type);
+    }
+
+    // STP over SDIO
+    else if ((mtk_wcn_stp_is_sdio_mode() || mtk_wcn_stp_is_uart_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_uart_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("%s: There is no winspace/txqueue to send !!!\n", __FUNCTION__);
+            }
+            ret = 0;
+        }
+
+        //osal_printtimeofday("[ STP][UART][ E][W]");
+    }
+    stp_ctx_unlock(&stp_core_ctx);
+       
+#ifdef CONFIG_POWER_SAVING_SUPPORT
+
+    if (MTK_WCN_BOOL_TRUE == stp_psm_is_quick_ps_support())
+    {
+        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((MTK_WCN_BOOL_FALSE == stp_is_privileges_cmd(buffer, length , type))) 
+                   {
+                       
+                       /*-----------------------------STP_PSM_UnLock----------------------------------------*/
+                       stp_psm_thread_lock_release(STP_PSM_CORE(stp_core_ctx));
+               }        
+       }
+    }
+ #endif
+    return ret;
+}
+
+/*****************************************************************************
+* 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
+*****************************************************************************/
+INT32 mtk_wcn_stp_send_data_raw (const UINT8 *buffer, const UINT32 length, const UINT8 type)
+{
+    UINT32 written = 0;
+    INT32 ret = 0;
+
+    if (0 != STP_WMT_LAST_CLOSE(stp_core_ctx)) {
+        STP_ERR_FUNC("WMT lats close,shoud 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
+
+    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);
+    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;
+}
+
+/*****************************************************************************
+* 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
+*****************************************************************************/
+INT32 mtk_wcn_stp_receive_data(UINT8 *buffer, UINT32 length, UINT8 type)
+{
+    /* GeorgeKuo modify: reduce "if" branch */
+    UINT16 copyLen = 0;
+    UINT16 tailLen = 0;
+    if ((MTK_WCN_BOOL_TRUE == stp_psm_is_quick_ps_support()) && (type != WMT_TASK_INDX))
+    {
+        stp_psm_disable_by_tx_rx_density(STP_PSM_CORE(stp_core_ctx), 1);
+    }
+
+    stp_ctx_lock(&stp_core_ctx);
+    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;
+            break;
+        }
+        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;
+        }
+    }
+
+    stp_ctx_unlock(&stp_core_ctx);
+
+    return copyLen;
+}
+
+/*****************************************************************************
+* 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
+*****************************************************************************/
+INT32 mtk_wcn_stp_is_rxqueue_empty(UINT8 type)
+{
+    INT32 ret;
+
+    stp_ctx_lock(&stp_core_ctx);
+
+    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
+    }
+
+    stp_ctx_unlock(&stp_core_ctx);
+
+    return ret;
+}
+
+/*****************************************************************************
+* 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_INFO_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_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
+    };
+
+    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);
+}
+
+void mtk_wcn_stp_debug_ctrl(INT32 op, INT32 filter, INT32 filter_param)
+{
+    return ;
+}
+
+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
+    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);
+    }
+
+    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)
+{
+    stp_ctx_lock(&stp_core_ctx);
+    if(type >= 0 && type < MTKSTP_MAX_TASK_NUM)
+    {
+        stp_core_ctx.ring[type].read_p = 0;
+        stp_core_ctx.ring[type].write_p = 0;
+    }
+    stp_ctx_unlock(&stp_core_ctx);
+}
+
+/*****************************************************************************
+* FUNCTION
+*  mtk_wcn_stp_is_enable
+* DESCRIPTION
+*  STP is ready?
+* PARAMETERS
+*  none.
+* RETURNS
+*  none
+*****************************************************************************/
+MTK_WCN_BOOL mtk_wcn_stp_is_ready(void)
+{
+    return STP_IS_READY(stp_core_ctx);
+}
+
+/*****************************************************************************
+* FUNCTION
+*  set_bluetooth_rx_interface
+* DESCRIPTION
+*  Set bluetooth rx interface
+* PARAMETERS
+*  rx interface type
+* RETURNS
+*  void
+*****************************************************************************/
+
+void mtk_wcn_stp_set_bluez(MTK_WCN_BOOL bluez_flag)
+{
+    //g_mtkstp_bluez_flag = bluez_flag;
+    STP_SET_BT_STK(stp_core_ctx, bluez_flag);
+}
+
+/*****************************************************************************
+* 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()
+{
+    return stp_psm_sleep_for_thermal(STP_PSM_CORE(stp_core_ctx));
+}
+
+EXPORT_SYMBOL(mtk_wcn_stp_dbg_level);
+
+
diff --git a/drivers/mtk_wcn_combo/common/core/stp_exp.c b/drivers/mtk_wcn_combo/common/core/stp_exp.c
new file mode 100755 (executable)
index 0000000..608add7
--- /dev/null
@@ -0,0 +1,259 @@
+/*******************************************************************************
+*                E X T E R N A L   R E F E R E N C E S
+********************************************************************************
+*/
+#if 0    //to do---- need check why need this header file
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/fcntl.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/timer.h>
+#include <linux/ctype.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/bitops.h>
+#include <linux/audit.h>
+#include <linux/file.h>
+#include <linux/module.h>
+
+#include <linux/spinlock.h>
+#include <linux/delay.h> /* udelay() */
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#endif
+#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 = NULL;
+static MTK_WCN_STP_IF_TX stp_sdio_if_tx = NULL;
+static ENUM_STP_TX_IF_TYPE g_stp_if_type = STP_MAX_IF_TX;
+static MTK_WCN_STP_IF_RX stp_if_rx = NULL;
+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);
+    }
+    else
+    {
+        (*stp_if_rx)(data, size);
+        return 0;
+    }
+}
+
+static INT32 mtk_wcn_sys_if_tx (
+    const UINT8 *data,
+    const UINT32 size,
+    UINT32 *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 (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 */
+        osal_dbg_print("[%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 >= 0 && 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;
+}
+
+INT32 mtk_wcn_stp_register_if_rx(MTK_WCN_STP_IF_RX func)
+{
+    stp_if_rx = func;
+
+    return 0;    
+}
+
+VOID mtk_wcn_stp_set_if_tx_type (
+    ENUM_STP_TX_IF_TYPE stp_if_type
+    )
+{
+    g_stp_if_type = stp_if_type;
+    osal_dbg_print("[%s] set STP_IF_TX to %s.\n",
+        __FUNCTION__,
+        (STP_UART_IF_TX == stp_if_type)? "UART" : ((STP_SDIO_IF_TX == stp_if_type) ? "SDIO" : "NULL"));
+}
+
+INT32 mtk_wcn_stp_register_if_tx (
+    ENUM_STP_TX_IF_TYPE stp_if,
+    MTK_WCN_STP_IF_TX func
+    )
+{
+    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 
+    {
+        osal_dbg_print("[%s] STP_IF_TX(%d) out of boundary.\n", __FUNCTION__, stp_if);
+        return -1;
+    }
+
+    return 0;
+}
+
+INT32 mtk_wcn_stp_register_event_cb(INT32 type, MTK_WCN_STP_EVENT_CB func)
+{
+    if (type < MTKSTP_MAX_TASK_NUM)
+    {
+        event_callback_tbl[type] = func;
+
+        /*clear rx queue*/
+        osal_dbg_print("Flush type = %d Rx Queue\n", type);
+        mtk_wcn_stp_flush_rx_queue(type);
+    }
+
+    return 0;
+}
+
+INT32 mtk_wcn_stp_register_tx_event_cb(INT32 type, MTK_WCN_STP_EVENT_CB func)
+{
+    if(type < MTKSTP_MAX_TASK_NUM)
+    {
+        tx_event_callback_tbl[type] = func;
+    }
+    else
+    {
+        osal_bug_on(0);
+    }
+
+    return 0;
+}
+
+INT32 stp_drv_init(VOID)
+{
+    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
+    };
+
+    return mtk_wcn_stp_init(&cb);
+}
+
+VOID stp_drv_exit(VOID)
+{
+    mtk_wcn_stp_deinit();
+
+    return;
+}
+
+EXPORT_SYMBOL(mtk_wcn_stp_register_if_tx);
+EXPORT_SYMBOL(mtk_wcn_stp_register_if_rx);
+EXPORT_SYMBOL(mtk_wcn_stp_register_event_cb);
+EXPORT_SYMBOL(mtk_wcn_stp_register_tx_event_cb);
+EXPORT_SYMBOL(mtk_wcn_stp_parser_data);
+EXPORT_SYMBOL(mtk_wcn_stp_send_data);
+EXPORT_SYMBOL(mtk_wcn_stp_send_data_raw);
+EXPORT_SYMBOL(mtk_wcn_stp_receive_data);
+EXPORT_SYMBOL(mtk_wcn_stp_is_rxqueue_empty);
+EXPORT_SYMBOL(mtk_wcn_stp_set_bluez);
+EXPORT_SYMBOL(mtk_wcn_stp_is_ready);
+EXPORT_SYMBOL(mtk_wcn_stp_dbg_log_ctrl);
+
+
+
+
+
diff --git a/drivers/mtk_wcn_combo/common/core/wmt_conf.c b/drivers/mtk_wcn_combo/common/core/wmt_conf.c
new file mode 100755 (executable)
index 0000000..09a6ecb
--- /dev/null
@@ -0,0 +1,525 @@
+
+#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 {
+    PCHAR name;
+    INT32 (*parser)(P_DEV_WMT pWmtDev, const struct parse_data *data,const PCHAR value);
+    PCHAR (*writer)(P_DEV_WMT pWmtDev, const struct parse_data *data);
+    /*PCHAR param1, *param2, *param3;*/
+    // TODO:[FixMe][George] CLARIFY WHAT SHOULD BE USED HERE!!!
+    PCHAR param1;
+    PCHAR param2;
+    PCHAR param3;
+};
+
+/*******************************************************************************
+*                        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
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                                 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 PCHAR pos
+    );
+
+static PCHAR 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 PCHAR pos
+    );
+
+static PCHAR 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 PCHAR pos
+    );
+
+static PCHAR wmt_conf_write_int(
+    P_DEV_WMT pWmtDev,
+    const struct parse_data *data
+    );
+
+static INT32 wmt_conf_parse_pair (
+    P_DEV_WMT pWmtDev,
+    const PCHAR pKey,
+    const PCHAR pVal
+    );
+
+static INT32 wmt_conf_parse (
+    P_DEV_WMT pWmtDev,
+    const PCHAR 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)
+#define CHAR(f) _CHAR(f), NULL, NULL
+
+#define _SHORT(f) #f, wmt_conf_parse_short, wmt_conf_write_short, OFFSET(rWmtGenConf.f)
+#define SHORT(f) _SHORT(f), NULL, NULL
+
+#define _INT(f) #f, wmt_conf_parse_int, wmt_conf_write_int, OFFSET(rWmtGenConf.f)
+#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_wifi_time_ctl) },
+    { CHAR(coex_wmt_ext_pta_dev_on) },
+
+    { 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 INT32 wmt_conf_parse_char(P_DEV_WMT pWmtDev, const struct parse_data *data,
+                 const PCHAR pos)
+{
+    PUCHAR dst;
+    dst = (PCHAR ) (((PUINT8) pWmtDev) + (LONG) data->param1);
+
+    if((osal_strlen(pos) > 2) &&
+        ((*pos)=='0') && (*(pos+1)=='x') ){
+        *dst = osal_strtol(pos+2, NULL, 16);
+        WMT_DBG_FUNC("wmtcfg==> %s=0x%x\n", data->name, *dst);
+    } else {
+        *dst = osal_strtol(pos, NULL, 10);
+        WMT_DBG_FUNC("wmtcfg==> %s=%d\n", data->name, *dst);
+    }
+    return 0;
+}
+
+static PCHAR  wmt_conf_write_char(P_DEV_WMT pWmtDev, const struct parse_data *data)
+{
+    PCHAR src;
+    INT32 res;
+    PCHAR value;
+
+    src = (PCHAR ) (((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_short(P_DEV_WMT pWmtDev, const struct parse_data *data,
+                 const PCHAR pos)
+{
+    PUINT16 dst;
+    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') ){
+        *dst = osal_strtol(pos+2, NULL, 16);
+        WMT_DBG_FUNC("wmtcfg==> %s=0x%x\n", data->name, *dst);
+    } else {
+        *dst = osal_strtol(pos, NULL, 10);
+        WMT_DBG_FUNC("wmtcfg==> %s=%d\n", data->name, *dst);
+    }
+
+    return 0;
+}
+
+static PCHAR  wmt_conf_write_short(P_DEV_WMT pWmtDev, const struct parse_data *data)
+{
+    PINT16 src;
+    INT32 res;
+    PCHAR 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 INT32 wmt_conf_parse_int(P_DEV_WMT pWmtDev, const struct parse_data *data,
+                 const PCHAR pos)
+{
+    PUINT32 dst;
+    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') ){
+        *dst = osal_strtol(pos+2, NULL, 16);
+        WMT_DBG_FUNC("wmtcfg==> %s=0x%x\n", data->name, *dst);
+    } else {
+        *dst = osal_strtol(pos, NULL, 10);
+        WMT_DBG_FUNC("wmtcfg==> %s=%d\n", data->name, *dst);
+    }
+
+    return 0;
+}
+
+static PCHAR  wmt_conf_write_int(P_DEV_WMT pWmtDev, const struct parse_data *data)
+{
+    PINT32 src;
+    INT32 res;
+    PCHAR 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 PCHAR pKey,
+    const PCHAR pVal
+    )
+{
+    INT32 i = 0;
+    INT32 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 PCHAR pInBuf,
+    UINT32 size
+    )
+{
+    CHAR *pch;
+    CHAR * pBuf;
+    CHAR * pLine;
+    CHAR * pKey;
+    CHAR * pVal;
+    CHAR * pPos;
+    INT32 ret = 0;
+    INT32 i = 0;
+    PCHAR 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
+    {
+        PCHAR 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_WARN_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_INFO_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 0
+    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_INFO_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_INFO_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 PCHAR)gDevWmt.pWmtCfg->data, gDevWmt.pWmtCfg->size))
+        {
+            /*config file exists*/
+            gDevWmt.rWmtGenConf.cfgExist = 1;
+
+            WMT_INFO_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;
+    }
+    else
+    {
+        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/mtk_wcn_combo/common/core/wmt_core.c b/drivers/mtk_wcn_combo/common/core/wmt_core.c
new file mode 100755 (executable)
index 0000000..d99ca66
--- /dev/null
@@ -0,0 +1,2025 @@
+/*! \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"
+
+#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_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_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.
+/* #define CFG_WMT_BT_PORT2 (1) */ /* BT Port 2 Feature.*/
+
+/*******************************************************************************
+*                             D A T A   T Y P E S
+********************************************************************************
+*/
+
+static WMT_CTX gMtkWmtCtx;
+static UINT8 gLpbkBuf[WMT_LPBK_BUF_LEN] = {0}; 
+
+/*******************************************************************************
+*                  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_sdio_ctrl (P_WMT_OP pWmtOp);
+static INT32 opfunc_pin_state (P_WMT_OP pWmtOp);
+static VOID wmt_core_dump_func_state (CHAR *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
+********************************************************************************
+*/
+
+const static UCHAR WMT_SLEEP_CMD[] = {0x01, 0x03, 0x01, 0x00, 0x01};
+const static UCHAR WMT_SLEEP_EVT[] = {0x02, 0x03, 0x02, 0x00, 0x00, 0x01};
+
+const static UCHAR WMT_HOST_AWAKE_CMD[] = {0x01, 0x03, 0x01, 0x00, 0x02};
+const static UCHAR WMT_HOST_AWAKE_EVT[] = {0x02, 0x03, 0x02, 0x00, 0x00, 0x02};
+
+const static UCHAR WMT_WAKEUP_CMD[] = {0xFF};
+const static UCHAR WMT_WAKEUP_EVT[] = {0x02, 0x03, 0x02, 0x00, 0x00, 0x03};
+
+static UCHAR WMT_THERM_CMD[] = {0x01, 0x11, 0x01, 0x00,
+    0x00 /*thermal sensor operation*/
+};
+static UCHAR WMT_THERM_CTRL_EVT[] = {0x02, 0x11, 0x01, 0x00, 0x00};
+static UCHAR WMT_THERM_READ_EVT[] = {0x02, 0x11, 0x02, 0x00, 0x00, 0x00};
+
+static UCHAR 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 UCHAR 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 UCHAR WMT_DSNS_CMD[] = {0x01, 0x0E, 0x02, 0x00, 0x01,
+    0x00 /*desnse type*/
+};
+static UCHAR WMT_DSNS_EVT[] = {0x02, 0x0E, 0x01, 0x00, 0x00 };
+
+// TODO:[NewFeature][GeorgeKuo] Update register group in ONE CMD/EVT
+static UCHAR 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 UCHAR 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 UCHAR 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 */
+};
+
+/* GeorgeKuo: Use designated initializers described in
+ * http://gcc.gnu.org/onlinedocs/gcc-4.0.4/gcc/Designated-Inits.html
+ */
+const static 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_SDIO_CTRL] = opfunc_sdio_ctrl,
+    [WMT_OPID_GPIO_STATE] = opfunc_pin_state,
+};
+
+/*******************************************************************************
+*                              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 UINT8 *pData,
+    const UINT32 size,
+    UINT32 *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);
+    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] = (UINT32)pBuf;
+    ctrlData.au4CtrlData[1] = bufLen;
+    ctrlData.au4CtrlData[2] = (UINT32)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;
+    }
+    else {
+        WMT_ERR_FUNC("WMT-CORE: wmt_func_ctrl_cmd 0x%x FAIL\n", rWmtPktCmd.aucParam[0]);
+        return -2;
+    }
+}
+
+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;
+    }
+    else {
+        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, PUINT32 pPa1, PUINT32 pPa2)
+{
+    INT32 iRet = -1;
+    WMT_CTRL_DATA ctrlData;
+    UINT32 val1 = (pPa1) ? *pPa1: 0;
+    UINT32 val2 = (pPa2) ? *pPa2 : 0;
+
+    ctrlData.ctrlId= (UINT32)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;
+        }
+        else {
+            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
+    )
+{
+    UCHAR 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 (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;
+    UINT32 ctrlPa1;
+    UINT32 ctrlPa2;
+    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 <0> turn on SDIO2 for common SDIO
+    if (WMT_HIF_SDIO == pctx->wmtHifConf.hifType) {
+        ctrlPa1 = WMT_SDIO_SLOT_SDIO2;
+        ctrlPa2 = 1; /* turn on SDIO2 slot */
+        iRet = wmt_core_ctrl(WMT_CTRL_SDIO_HW, &ctrlPa1, &ctrlPa2) ;
+        if (iRet) {
+            WMT_ERR_FUNC("WMT-CORE: turn on SLOT_SDIO2 fail (%d)\n", iRet);
+            osal_assert(0);
+
+            return -2;
+        }
+        pctx->eDrvStatus[WMTDRV_TYPE_SDIO2] = DRV_STS_FUNC_ON;
+
+        ctrlPa1 = WMT_SDIO_FUNC_STP;
+        ctrlPa2 = 1; /* turn on STP driver */
+        iRet = wmt_core_ctrl(WMT_CTRL_SDIO_FUNC, &ctrlPa1, &ctrlPa2) ;
+        if (iRet) {
+            WMT_ERR_FUNC("WMT-CORE: turn on SDIO_FUNC_STP func fail (%d)\n", iRet);
+
+            /* check all sub-func and do power off */
+            return -3;
+        }
+    }
+
+    //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 -4;
+    }
+
+    if (WMT_HIF_UART == pctx->wmtHifConf.hifType) {
+        ctrlPa1 = WMT_DEFAULT_BAUD_RATE; ctrlPa2 = 0;
+        iRet = wmt_core_ctrl(WMT_CTRL_HOST_BAUDRATE_SET, &ctrlPa1, &ctrlPa2);
+        if (iRet) {
+            WMT_ERR_FUNC("WMT-CORE: change host baudrate(%d) fails \n", pctx->wmtHifConf.au4HifConf[0]);
+            return -5;
+        }
+    }
+    //WMT_DBG_FUNC("WMT-CORE: change host baudrate(%d) ok \n", gMtkWmtCtx.wmtHifConf.au4HifConf[0]);
+
+    //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_UART == pctx->wmtHifConf.hifType) {
+        ctrlPa1 = WMT_STP_CONF_MODE; ctrlPa2 = MTKSTP_UART_MAND_MODE;
+        iRet += wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2);
+    }
+    else if (WMT_HIF_SDIO == pctx->wmtHifConf.hifType) {
+        ctrlPa1 = WMT_STP_CONF_MODE; ctrlPa2 = MTKSTP_SDIO_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 -7;
+    }
+
+    // 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 -8;
+    }
+    /* mtkWmtCtx.p_ic_ops is identified and checked ok */
+    if ((NULL != pctx->p_ic_ops->co_clock_ctrl) && (pWmtGenConf != NULL))      
+       {
+           (*(pctx->p_ic_ops->co_clock_ctrl))(pWmtGenConf->co_clock_flag == 0 ? WMT_CO_CLOCK_DIS : WMT_CO_CLOCK_EN);   
+       }       
+       else    
+       {
+           WMT_INFO_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 -9;
+    }
+    if (iRet) {
+        WMT_ERR_FUNC("gMtkWmtCtx.p_ic_ops->sw_init fail:%d\n", iRet);
+        return -10;
+    }
+
+    //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;
+    UINT32 ctrlPa1;
+    UINT32 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);
+
+    //4 <1.1> turn off SDIO2 for common SDIO
+    if (WMT_HIF_SDIO == gMtkWmtCtx.wmtHifConf.hifType) {
+        ctrlPa1 = WMT_SDIO_FUNC_STP;
+        ctrlPa2 = 0; /* turn off STP driver */
+        iRet = wmt_core_ctrl(WMT_CTRL_SDIO_FUNC, &ctrlPa1, &ctrlPa2) ;
+        if (iRet) {
+            WMT_WARN_FUNC("turn off SDIO_FUNC_STP fail (%d)\n", iRet);
+            /* Anyway, continue turning SDIO HW off */
+        }
+        else {
+            WMT_INFO_FUNC("turn off SDIO_FUNC_STP ok \n");
+        }
+
+        ctrlPa1 = WMT_SDIO_SLOT_SDIO2;
+        ctrlPa2 = 0; /* turn off SDIO2 slot */
+        iRet = wmt_core_ctrl(WMT_CTRL_SDIO_HW, &ctrlPa1, &ctrlPa2) ;
+        if (iRet) {
+            WMT_WARN_FUNC("turn off SDIO2 HW fail (%d)\n", iRet);
+            /* Anyway, continue turning STP SDIO to POWER OFF state*/
+        }
+        else {
+            WMT_INFO_FUNC("turn off SDIO2 HW ok \n");
+        }
+        gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_SDIO2] = DRV_STS_POWER_OFF;
+    }
+
+    if (iRet) {
+        WMT_WARN_FUNC("end with fail:%d\n", iRet);
+    }
+
+    return iRet;
+}
+
+static VOID
+wmt_core_dump_func_state (
+    CHAR *pSource
+    )
+{
+   WMT_INFO_FUNC("[%s]status(b:%d f:%d g:%d w:%d lpbk:%d coredump:%d wmt:%d sd1:%d sd2:%d stp:%d)\n",
+        (pSource == NULL ? (CHAR *)"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_SDIO1],
+        gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_SDIO2],
+        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_INFO_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
+    default:
+        p_ops = (P_WMT_IC_OPS)NULL;
+        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);
+
+    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_INFO_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;
+    UINT32 ctrlPa1;
+    UINT32 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;
+    UINT32 ctrlPa1;
+    UINT32 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;
+    }
+
+    /* 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);
+    }
+    else {
+        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;
+    UINT32 ctrlPa1;
+    UINT32 ctrlPa2;
+
+    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;
+    }
+
+    /* 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)
+        {
+
+            /* special handling for Wi-Fi */
+            if (WMTDRV_TYPE_WIFI == drvType) {
+                if (WMT_HIF_UART == gMtkWmtCtx.wmtHifConf.hifType) {
+                    ctrlPa1 = WMT_SDIO_SLOT_SDIO1;
+                    ctrlPa2 = 1; /* turn on SDIO1 slot */
+                    iRet = wmt_core_ctrl(WMT_CTRL_SDIO_HW, &ctrlPa1, &ctrlPa2) ;
+                    if (iRet) {
+                           WMT_ERR_FUNC("turn on SLOT_SDIO1 fail (%d)\n", iRet);
+                           osal_assert(0);
+                        /* check all sub-func and do power off */
+                    }
+                    else {
+                          gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_SDIO1] = DRV_STS_FUNC_ON;
+                    }
+                }
+                else if (WMT_HIF_SDIO == gMtkWmtCtx.wmtHifConf.hifType) {
+                       if (DRV_STS_FUNC_ON == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_SDIO2]) {
+                           WMT_DBG_FUNC("SLOT_SDIO2 ready for WIFI\n");
+                    }
+                       else {
+                       /* SDIO2 slot power shall be either turned on in STP init
+                                          * procedures already, or failed in STP init before. Here is
+                                          * the assert condition.
+                                        **/
+                        WMT_ERR_FUNC("WMT-CORE: turn on Wi-Fi in comm SDIO2 but SDIO in FUNC_OFF state(0x%x)\n", gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_SDIO2]);
+                        osal_assert(0);
+                        return -4;
+                    }
+                }
+                else {
+                    WMT_ERR_FUNC("WMT-CORE: error, not implemented yet gMtkWmtCtx.wmtHifConf.hifType: 0x%x, unspecified wifi_hif\n", gMtkWmtCtx.wmtHifConf.hifType);
+                    // TODO:  Wi-Fi/WMT uses other interfaces. NOT IMPLEMENTED YET!
+                }
+
+            }
+            iRet = (*(gpWmtFuncOps[drvType]->func_on))(gMtkWmtCtx.p_ic_ops, wmt_conf_get_cfg());
+            if (0 != iRet)
+            {
+                if (WMTDRV_TYPE_WIFI == drvType && WMT_HIF_UART == gMtkWmtCtx.wmtHifConf.hifType) {
+                    /*need to power SDIO off when Power on Wi-Fi fail, in case of power leakage and right SDIO power status maintain*/
+                    ctrlPa1 = WMT_SDIO_SLOT_SDIO1;
+                    ctrlPa2 = 0; /* turn off SDIO1 slot */
+                    wmt_core_ctrl(WMT_CTRL_SDIO_HW, &ctrlPa1, &ctrlPa2) ;
+                    //does not need to check turn off result
+                    gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_SDIO1] = DRV_STS_POWER_OFF;
+                    
+                }
+                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);
+
+            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;
+    UINT32 ctrlPa1;
+    UINT32 ctrlPa2;
+
+    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());
+
+            if (WMTDRV_TYPE_WIFI == drvType && WMT_HIF_UART == gMtkWmtCtx.wmtHifConf.hifType) {
+                UINT32 iRet = 0;
+                ctrlPa1 = WMT_SDIO_SLOT_SDIO1;
+                ctrlPa2 = 0; /* turn off SDIO1 slot */
+                iRet = wmt_core_ctrl(WMT_CTRL_SDIO_HW, &ctrlPa1, &ctrlPa2) ;
+                if (iRet) {
+                    WMT_ERR_FUNC("WMT-CORE: turn on SLOT_SDIO1 fail (%d)\n", iRet);
+                    osal_assert(0);
+                    /* check all sub-func and do power off */
+                }
+                //Anyway, turn SDIO1 state to POWER_OFF state
+                gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_SDIO1] = DRV_STS_POWER_OFF;
+            }
+        }
+        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;
+    UINT32 evt_len;
+    UINT8 evt_buf[16] = {0};
+
+typedef INT32 (*STP_PSM_CB)(INT32);
+    STP_PSM_CB  psm_cb;
+
+    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(&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))
+        {
+            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();
+            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] exp(%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],
+                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_INFO_FUNC("Send sleep command OK!\n");
+        }
+    }
+    else if (pWmtOp->au4OpData[0] == WAKEUP)
+    {
+        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;
+        }
+
+        evt_len = sizeof(WMT_WAKEUP_EVT);
+        ret = wmt_core_rx(evt_buf, evt_len, &u4_result);
+        if (ret || (u4_result != evt_len))
+        {
+            WMT_ERR_FUNC("wmt_core: read WAKEUP_EVT fail(%d) len(%d, %d)", ret, u4_result, evt_len);
+            mtk_wcn_stp_dbg_dump_package();
+            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] exp(%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],
+                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_INFO_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(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))
+        {
+            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();
+            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] exp(%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],
+                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_INFO_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\n", pWmtOp->au4OpData[0], (PVOID)pWmtOp->au4OpData[1]);
+        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] = pWmtOp->au4OpData[0];
+    WMT_DSNS_CMD[5] = 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;
+}
+
+
+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");
+    /*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;
+    }
+    /*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;
+        }
+        /*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;
+        }
+        /*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;
+        }
+        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;
+    UINT32  tstCmdSz = 0;
+    UINT32  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_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 = (UINT8 *)pWmtOp->au4OpData[2];
+        resBufRoom = pWmtOp->au4OpData[3];
+        if ((cmdNoPa >= 0x0) && (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 >= 0x0 && 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 {
+         /*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)) {
+        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 {
+            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;
+    UINT32 ctrlPa1;
+    UINT32 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_SDIO1]= DRV_STS_POWER_OFF;
+    //gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_SDIO2]= DRV_STS_POWER_OFF;
+    gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_STP]  = DRV_STS_POWER_OFF;
+
+    /* if wmt is poweroff, we need poweron chip first*/
+    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;
+    }
+    
+    /*--> reset SDIO fucntion/slot additionally if wifi ON*/
+    if (gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WIFI] == DRV_STS_FUNC_ON) {
+            ctrlPa1 = WMT_SDIO_FUNC_WIFI;
+            ctrlPa2 = 0;     /* turn off Wi-Fi driver */
+            iRet = wmt_core_ctrl(WMT_CTRL_SDIO_FUNC, &ctrlPa1, &ctrlPa2) ;
+            if (iRet) {
+                WMT_ERR_FUNC("WMT-CORE: turn off SDIO_WIFI func fail (%d)\n", iRet);
+
+                /* check all sub-func and do power off */
+            } else {
+                WMT_INFO_FUNC("wmt core: turn off SDIO WIFI func ok!!\n");
+            }
+            //Anyway, turn off Wi-Fi Function
+            gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WIFI] = DRV_STS_POWER_OFF;
+
+        if (WMT_HIF_UART == gMtkWmtCtx.wmtHifConf.hifType) {
+            ctrlPa1 = WMT_SDIO_SLOT_SDIO1;
+            ctrlPa2 = 0;     /* turn off SDIO1 slot */
+            iRet = wmt_core_ctrl(WMT_CTRL_SDIO_HW, &ctrlPa1, &ctrlPa2) ;
+            if (iRet) {
+                WMT_ERR_FUNC("WMT-CORE: turn off SLOT_SDIO1 fail (%d)\n", iRet);
+                osal_assert(0);
+
+                /* check all sub-func and do power off */
+            } else {
+                WMT_INFO_FUNC("WMT-CORE: turn off SLOT_SDIO1 successfully (%d)\n", iRet);
+            }
+            gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_SDIO1] = DRV_STS_POWER_OFF;
+        }
+        gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WIFI] = DRV_STS_POWER_OFF;
+    }
+
+    if (WMT_HIF_SDIO == gMtkWmtCtx.wmtHifConf.hifType) {
+        ctrlPa1 = WMT_SDIO_FUNC_STP;
+        ctrlPa2 = 0; /* turn off STP driver */
+        iRet = wmt_core_ctrl(WMT_CTRL_SDIO_FUNC, &ctrlPa1, &ctrlPa2) ;
+        if (iRet) {
+            WMT_ERR_FUNC("WMT-CORE: turn off SDIO_FUNC_STP func fail (%d)\n", iRet);
+
+            /* check all sub-func and do power off */
+            //goto stp_deinit_done;
+        } else {
+            WMT_INFO_FUNC("WMT-CORE: turn off SDIO_FUNC_STP func successfully (%d)\n", iRet);
+        }
+
+        ctrlPa1 = WMT_SDIO_SLOT_SDIO2;
+        ctrlPa2 = 0; /* turn off SDIO2 slot */
+        iRet = wmt_core_ctrl(WMT_CTRL_SDIO_HW, &ctrlPa1, &ctrlPa2) ;
+        if (iRet) {
+            WMT_ERR_FUNC("WMT-CORE: turn off SLOT_SDIO2 fail (%d)\n", iRet);
+            osal_assert(0);
+
+            /* check all sub-func and do power off */
+            //goto stp_deinit_done;
+        } else {
+            WMT_INFO_FUNC("WMT-CORE: turn off SLOT_SDIO2 successfully (%d)\n", iRet);
+        }
+            gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_SDIO2] = 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);
+    } else {
+        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);
+    } else {
+        WMT_INFO_FUNC("WMT-CORE: -->[HW RST] ok\n");
+    }
+
+    //4  close stp
+    ctrlPa1 = 0; ctrlPa2 = 0;
+    iRet = wmt_core_ctrl(WMT_CTRL_STP_CLOSE, &ctrlPa1, &ctrlPa2);
+    if (iRet) {
+        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)
+{
+#if 0
+    UINT32 iRet = -1;
+    if (NULL != gMtkWmtCtx.p_ic_ops->swInit)
+    {
+        iRet = (*(gMtkWmtCtx.p_ic_ops->swInit))(&gMtkWmtCtx.wmtHifConf);
+    }
+    else
+    {
+        WMT_ERR_FUNC("WMT-CORE: error, gMtkWmtCtx.p_ic_ops->swInit(NULL)\n");
+        return -1;
+    }
+    if (0 == iRet)
+    {
+        WMT_ERR_FUNC("WMT-CORE: WMT-->[FUNC_ON] succeed\n");
+        gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] = DRV_STS_FUNC_ON;
+        return 0;
+    }
+    return -2;
+#endif
+
+    return wmt_core_stp_init();
+}
+
+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_INFO_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_INFO_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;
+}
+
+//turn on/off sdio function
+INT32 opfunc_sdio_ctrl (P_WMT_OP pWmtOp)
+{
+    UINT32 ctrlPa1 = 0;
+    UINT32 ctrlPa2 = 0;
+    UINT32 iRet = 0;
+    ctrlPa1 = WMT_HIF_SDIO == gMtkWmtCtx.wmtHifConf.hifType ?     WMT_SDIO_SLOT_SDIO2 :     WMT_SDIO_SLOT_SDIO1;
+    ctrlPa2 = pWmtOp->au4OpData[0]; /* turn off/on SDIO slot */
+    iRet = wmt_core_ctrl(WMT_CTRL_SDIO_HW, &ctrlPa1, &ctrlPa2) ;
+    if (iRet) {
+        WMT_WARN_FUNC("SDIO hw ctrl fail ret(%d)\n", iRet);
+        /* Anyway, continue turning STP SDIO to POWER OFF/ON state*/
+        gMtkWmtCtx.eDrvStatus[ctrlPa1] = DRV_STS_POWER_OFF;
+    }
+    else {
+        WMT_INFO_FUNC("SDIO hw ctrl succeed  \n");
+        gMtkWmtCtx.eDrvStatus[ctrlPa1] = 0 ==ctrlPa2 ? DRV_STS_POWER_OFF : DRV_STS_POWER_ON;
+    }
+
+    return 0;
+
+}
+
+
+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)
+{
+    
+    UINT32 ctrlPa1 = 0;
+    UINT32 ctrlPa2 = 0;
+    UINT32 iRet = 0;
+       iRet = wmt_core_ctrl(WMT_CTRL_HW_STATE_DUMP, &ctrlPa1, &ctrlPa2) ;
+       return iRet;
+}
+
+
+
diff --git a/drivers/mtk_wcn_combo/common/core/wmt_ctrl.c b/drivers/mtk_wcn_combo/common/core/wmt_ctrl.c
new file mode 100755 (executable)
index 0000000..eff9b46
--- /dev/null
@@ -0,0 +1,946 @@
+/*! \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_lib.h"
+#include "wmt_dev.h"
+#include "wmt_plat.h"
+#include "hif_sdio.h"
+#include "stp_core.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);
+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);
+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);
+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_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
+********************************************************************************
+*/
+
+// TODO:[FixMe][GeorgeKuo]: use module APIs instead of direct access to internal data
+extern DEV_WMT gDevWmt;
+
+/*******************************************************************************
+*                           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
+ */
+const static 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_HOST_BAUDRATE_SET] = wmt_ctrl_host_baudrate_set,
+    [WMT_CTRL_SDIO_HW] = wmt_ctrl_sdio_hw,
+    [WMT_CTRL_SDIO_FUNC] = wmt_ctrl_sdio_func,
+    [WMT_CTRL_HWIDVER_SET] = wmt_ctrl_hwidver_set,
+    [WMT_CTRL_HWVER_GET] = NULL, // TODO: [FixMe][GeorgeKuo]: remove unused function.
+    [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_MAX] = wmt_ctrl_others,
+};
+
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+
+INT32  wmt_ctrl (P_WMT_CTRL_DATA pWmtCtrlData)
+{
+    UINT32 ctrlId = pWmtCtrlData->ctrlId;
+
+    if (NULL == pWmtCtrlData) {
+        osal_assert(0);
+        return -1;
+    }
+
+    /*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 */
+    }
+    else {
+        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 = (UINT8 *)pWmtCtrlData->au4CtrlData[0];
+    UINT32 size = pWmtCtrlData->au4CtrlData[1];
+    UINT32 *writtenSize = (UINT32 *)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;
+    UINT8 *pBuff = (UINT8 *)pWmtCtrlData->au4CtrlData[0];
+    UINT32 buffLen = pWmtCtrlData->au4CtrlData[1];
+    UINT32 *readSize = (UINT32 *)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 \n");
+            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);
+        }
+        WMT_DBG_FUNC("readLen(%d) \n", readLen);
+    }
+
+    if (readSize) {
+        *readSize = readLen ;
+    }
+
+    return 0;
+
+}
+
+
+INT32
+wmt_ctrl_tx_ex (
+    const UINT8 *pData,
+    const UINT32 size,
+    UINT32 *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 UCHAR *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_INFO_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;
+    UCHAR cmdStr[NAME_MAX + 1] = {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;
+    }
+
+    if (WMT_HIF_UART == pDev->rWmtHifConf.hifType) {
+
+        osal_snprintf(cmdStr, NAME_MAX, "close_stp");
+
+        iRet = wmt_ctrl_ul_cmd(pDev, cmdStr);
+        if (iRet) {
+            WMT_WARN_FUNC("wmt_ctrl_ul_cmd fail(%d)\n", iRet);
+            return -2;
+        }
+    }
+
+    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;
+    UCHAR cmdStr[NAME_MAX + 1] = {0};
+
+    if (WMT_HIF_UART == pDev->rWmtHifConf.hifType) {
+        osal_snprintf(cmdStr, NAME_MAX, "open_stp");
+        iRet = wmt_ctrl_ul_cmd(pDev, cmdStr);
+        if (iRet) {
+            WMT_WARN_FUNC("wmt_ctrl_ul_cmd fail(%d)\n", iRet);
+            return -1;
+        }
+    }
+
+    /* register to STP-core for rx */
+    iRet = mtk_wcn_stp_register_event_cb(WMT_TASK_INDX, wmt_dev_rx_event_cb); /* mtk_wcn_stp_register_event_cb */
+    if (iRet) {
+        WMT_WARN_FUNC("stp_reg cb fail(%d)\n", iRet);
+        return -2;
+    }
+
+    osal_set_bit(WMT_STAT_STP_OPEN, &pDev->state);
+
+    return 0;
+}
+
+
+INT32  wmt_ctrl_patch_search(P_WMT_CTRL_DATA pWmtCtrlData)
+{
+    P_DEV_WMT pDev = &gDevWmt; /* single instance */
+    INT32 iRet;
+    UCHAR 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;
+       PUCHAR pNbuf = NULL;
+       PUCHAR pAbuf =NULL;
+       
+       downLoadSeq = pWmtCtrlData->au4CtrlData[0];
+       WMT_DBG_FUNC("download seq is %d\n",downLoadSeq);
+
+       pPatchinfo = pDev->pWmtPatchInfo + downLoadSeq - 1;
+       pNbuf = (PUCHAR)pWmtCtrlData->au4CtrlData[1];
+       pAbuf = (PUCHAR)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_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)
+{
+    PUCHAR pBuf = (PUCHAR)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;
+     UCHAR *pFileName = (UCHAR *)pWmtCtrlData->au4CtrlData[0];
+        PUINT8 *ppBuf = (PUINT8 *)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)
+{
+    UCHAR *pFullPatchName = NULL;
+    UCHAR *pDefPatchName = NULL;
+    PUINT8 *ppBuf = (PUINT8 *)pWmtCtrlData->au4CtrlData[2];
+    PUINT32 pSize = (PUINT32)pWmtCtrlData->au4CtrlData[3];
+
+    osal_firmware *pPatch = NULL;
+    pFullPatchName = (UCHAR *)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 = (UCHAR *)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;
+
+}
+
+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;
+}
+
+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_msleep(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;
+}
+
+#if 0 // TODO: [FixMe][GeorgeKuo]: remove unused function. get hwver from core is not needed.
+INT32  wmt_ctrl_hwver_get(P_WMT_CTRL_DATA pWmtCtrlData)
+{
+    P_DEV_WMT pDev = &gDevWmt; /* single instance */
+    return 0;
+}
+#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;
+}
+
+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] = (UINT32)&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/mtk_wcn_combo/common/core/wmt_dbg.c b/drivers/mtk_wcn_combo/common/core/wmt_dbg.c
new file mode 100755 (executable)
index 0000000..03fb7a3
--- /dev/null
@@ -0,0 +1,706 @@
+/* Copyright Statement:\r
+ *\r
+ * This software/firmware and related documentation ("MediaTek Software") are\r
+ * protected under relevant copyright laws. The information contained herein\r
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.\r
+ * Without the prior written permission of MediaTek inc. and/or its licensors,\r
+ * any reproduction, modification, use or disclosure of MediaTek Software,\r
+ * and information contained herein, in whole or in part, shall be strictly prohibited.\r
+ *\r
+ * MediaTek Inc. (C) 2010. All rights reserved.\r
+ *\r
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES\r
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")\r
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON\r
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.\r
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE\r
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR\r
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH\r
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES\r
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES\r
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK\r
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR\r
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND\r
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,\r
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,\r
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO\r
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.\r
+ *\r
+ * The following software/firmware and/or related documentation ("MediaTek Software")\r
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's\r
+ * applicable license agreements with MediaTek Inc.\r
+ */\r
+\r
+\r
+/*! \file\r
+    \brief brief description\r
+\r
+    Detailed descriptions here.\r
+\r
+*/\r
+\r
+/*******************************************************************************\r
+* Copyright (c) 2009 MediaTek Inc.\r
+*\r
+* All rights reserved. Copying, compilation, modification, distribution\r
+* or any other use whatsoever of this material is strictly prohibited\r
+* except in accordance with a Software License Agreement with\r
+* MediaTek Inc.\r
+********************************************************************************\r
+*/\r
+\r
+/*******************************************************************************\r
+* LEGAL DISCLAIMER\r
+*\r
+* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND\r
+* AGREES THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK\r
+* SOFTWARE") RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE\r
+* PROVIDED TO BUYER ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY\r
+* DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT\r
+* LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\r
+* PARTICULAR PURPOSE OR NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE\r
+* ANY WARRANTY WHATSOEVER WITH RESPECT TO THE SOFTWARE OF ANY THIRD PARTY\r
+* WHICH MAY BE USED BY, INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK\r
+* SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY\r
+* WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE\r
+* FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S SPECIFICATION OR TO\r
+* CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.\r
+*\r
+* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE\r
+* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL\r
+* BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT\r
+* ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY\r
+* BUYER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.\r
+*\r
+* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE\r
+* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT\r
+* OF LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING\r
+* THEREOF AND RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN\r
+* FRANCISCO, CA, UNDER THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE\r
+* (ICC).\r
+********************************************************************************\r
+*/\r
+\r
+/*******************************************************************************\r
+*                         C O M P I L E R   F L A G S\r
+********************************************************************************\r
+*/\r
+\r
+/*******************************************************************************\r
+*                                 M A C R O S\r
+********************************************************************************\r
+*/\r
+\r
+#include "wmt_dbg.h"\r
+#include "wmt_core.h"\r
+#include "wmt_lib.h"\r
+#include "wmt_conf.h"\r
+#include "psm_core.h"\r
+#include "stp_core.h"\r
+\r
+#if CFG_WMT_DBG_SUPPORT\r
+\r
+\r
+#ifdef DFT_TAG\r
+#undef DFT_TAG\r
+#endif\r
+#define DFT_TAG         "[WMT-DEV]"\r
+\r
+\r
+\r
+#define WMT_DBG_PROCNAME "driver/wmt_dbg"\r
+\r
+static struct proc_dir_entry *gWmtDbgEntry = NULL;\r
+COEX_BUF gCoexBuf;\r
+\r
+static INT32 wmt_dbg_psm_ctrl(INT32 par1, INT32 par2, INT32 par3);\r
+static INT32 wmt_dbg_dsns_ctrl(INT32 par1, INT32 par2, INT32 par3);\r
+static INT32 wmt_dbg_hwver_get(INT32 par1, INT32 par2, INT32 par3);\r
+static INT32 wmt_dbg_inband_rst(INT32 par1, INT32 par2, INT32 par3);\r
+static INT32 wmt_dbg_chip_rst(INT32 par1, INT32 par2, INT32 par3);\r
+static INT32 wmt_dbg_func_ctrl(INT32 par1, INT32 par2, INT32 par3);\r
+static INT32 wmt_dbg_raed_chipid(INT32 par1, INT32 par2, INT32 par3);\r
+static INT32 wmt_dbg_wmt_dbg_level(INT32 par1, INT32 par2, INT32 par3);\r
+static INT32 wmt_dbg_stp_dbg_level(INT32 par1, INT32 par2, INT32 par3);\r
+static INT32 wmt_dbg_reg_read(INT32 par1, INT32 par2, INT32 par3);\r
+static INT32 wmt_dbg_reg_write(INT32 par1, INT32 par2, INT32 par3);\r
+static INT32 wmt_dbg_coex_test(INT32 par1, INT32 par2, INT32 par3);\r
+static INT32 wmt_dbg_assert_test(INT32 par1, INT32 par2, INT32 par3);\r
+static INT32 wmt_dbg_cmd_test_api(ENUM_WMTDRV_CMD_T cmd);\r
+static INT32 wmt_dbg_rst_ctrl(INT32 par1, INT32 par2, INT32 par3);\r
+static INT32 wmt_dbg_ut_test(INT32 par1, INT32 par2, INT32 par3);\r
+static INT32 wmt_dbg_efuse_read(INT32 par1, INT32 par2, INT32 par3);\r
+static INT32 wmt_dbg_efuse_write(INT32 par1, INT32 par2, INT32 par3);\r
+static INT32 wmt_dbg_sdio_ctrl(INT32 par1, INT32 par2, INT32 par3);\r
+static INT32 wmt_dbg_stp_dbg_ctrl(INT32 par1, INT32 par2, INT32 par3);\r
+static INT32 wmt_dbg_stp_dbg_log_ctrl(INT32 par1, INT32 par2, INT32 par3);\r
+static INT32 wmt_dbg_wmt_assert_ctrl(INT32 par1, INT32 par2, INT32 par3);\r
+\r
+\r
+\r
+\r
+\r
+const static WMT_DEV_DBG_FUNC wmt_dev_dbg_func[] =\r
+{\r
+    [0] = wmt_dbg_psm_ctrl,\r
+    [1] = wmt_dbg_psm_ctrl,\r
+    [2] = wmt_dbg_dsns_ctrl,\r
+    [3] = wmt_dbg_hwver_get,\r
+    [4] = wmt_dbg_assert_test,\r
+    [5] = wmt_dbg_inband_rst,\r
+    [6] = wmt_dbg_chip_rst,\r
+    [7] = wmt_dbg_func_ctrl,\r
+    [8] = wmt_dbg_raed_chipid,\r
+    [9] = wmt_dbg_wmt_dbg_level,\r
+    [0xa] = wmt_dbg_stp_dbg_level,\r
+    [0xb] = wmt_dbg_reg_read,\r
+    [0xc] = wmt_dbg_reg_write,\r
+    [0xd] = wmt_dbg_coex_test, \r
+    [0xe] = wmt_dbg_rst_ctrl,\r
+    [0xf] = wmt_dbg_ut_test,\r
+    [0x10] = wmt_dbg_efuse_read,\r
+    [0x11] = wmt_dbg_efuse_write,\r
+    [0x12] = wmt_dbg_sdio_ctrl,\r
+    [0x13] = wmt_dbg_stp_dbg_ctrl,\r
+    [0x14] = wmt_dbg_stp_dbg_log_ctrl,\r
+    [0x15] = wmt_dbg_wmt_assert_ctrl,\r
+};\r
+\r
+INT32 wmt_dbg_psm_ctrl(INT32 par1, INT32 par2, INT32 par3)\r
+{\r
+#if CFG_WMT_PS_SUPPORT\r
+    if (0 == par2)\r
+    {\r
+        wmt_lib_ps_ctrl(0);\r
+        WMT_INFO_FUNC("disable PSM\n");\r
+    }\r
+    else\r
+    {\r
+        par2 = (1 > par2 || 20000 < par2) ? STP_PSM_IDLE_TIME_SLEEP : par2;\r
+        wmt_lib_ps_set_idle_time(par2);\r
+        wmt_lib_ps_ctrl(1);\r
+        WMT_INFO_FUNC("enable PSM, idle to sleep time = %d ms\n", par2);\r
+    }\r
+#else\r
+    WMT_INFO_FUNC("WMT PS not supported\n");\r
+#endif    \r
+    return 0;\r
+}\r
+\r
+INT32 wmt_dbg_dsns_ctrl(INT32 par1, INT32 par2, INT32 par3)\r
+{\r
+    if (WMTDSNS_FM_DISABLE <= par2 && WMTDSNS_MAX > par2 )\r
+    {\r
+        WMT_INFO_FUNC("DSNS type (%d)\n", par2);\r
+        mtk_wcn_wmt_dsns_ctrl(par2);\r
+    }\r
+    else\r
+    {\r
+        WMT_WARN_FUNC("invalid DSNS type\n");\r
+    }\r
+    return 0;\r
+}\r
+\r
+INT32 wmt_dbg_hwver_get(INT32 par1, INT32 par2, INT32 par3)\r
+{\r
+    WMT_INFO_FUNC("query chip version\n");\r
+    mtk_wcn_wmt_hwver_get();\r
+    return 0;\r
+}\r
+\r
+INT32 wmt_dbg_assert_test(INT32 par1, INT32 par2, INT32 par3)\r
+{\r
+    if (0 == par3)\r
+    {\r
+    //par2 = 0:  send assert command\r
+    //par2 != 0: send exception command\r
+        return wmt_dbg_cmd_test_api(0 == par2 ? 0 : 1);\r
+    }\r
+    else\r
+    {\r
+        INT32 sec = 8;\r
+        INT32 times = 0;\r
+        times = par3;\r
+        do{\r
+            WMT_INFO_FUNC("Send Assert Command per 8 secs!!\n");\r
+            wmt_dbg_cmd_test_api(0);\r
+            osal_msleep(sec * 1000);\r
+        }while(--times);\r
+    }\r
+    return 0;\r
+}\r
+\r
+INT32 wmt_dbg_cmd_test_api(ENUM_WMTDRV_CMD_T cmd)\r
+{\r
+    \r
+    P_OSAL_OP pOp = NULL;\r
+    MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE;\r
+    P_OSAL_SIGNAL pSignal;\r
+    \r
+    pOp  = wmt_lib_get_free_op();\r
+    if (!pOp ) {\r
+        WMT_WARN_FUNC("get_free_lxop fail\n");\r
+        return MTK_WCN_BOOL_FALSE;\r
+    }\r
+\r
+    pSignal = &pOp ->signal;\r
+\r
+    pOp ->op.opId = WMT_OPID_CMD_TEST;\r
+    \r
+    pSignal->timeoutValue= MAX_EACH_WMT_CMD;\r
+    /*this test command should be run with usb cable connected, so no host awake is needed*/\r
+    //wmt_lib_host_awake_get();\r
+    switch (cmd)\r
+    {\r
+        case WMTDRV_CMD_ASSERT:\r
+            pOp->op.au4OpData[0] = 0;\r
+        break;\r
+        case WMTDRV_CMD_EXCEPTION:\r
+            pOp->op.au4OpData[0] = 1;\r
+        break;\r
+        default:\r
+            if (WMTDRV_CMD_COEXDBG_00 <= cmd && WMTDRV_CMD_COEXDBG_15 >= cmd)\r
+            {\r
+                pOp->op.au4OpData[0] = 2;\r
+                pOp->op.au4OpData[1] = cmd - 2;\r
+            }\r
+            else\r
+            {\r
+                pOp->op.au4OpData[0] = 0xff;\r
+                pOp->op.au4OpData[1] = 0xff;\r
+            }\r
+            pOp->op.au4OpData[2] = (ULONG)gCoexBuf.buffer;\r
+            pOp->op.au4OpData[3] = osal_sizeof(gCoexBuf.buffer);\r
+        break;\r
+    }\r
+    WMT_INFO_FUNC("CMD_TEST, opid(%d), par(%d, %d)\n", pOp->op.opId, pOp->op.au4OpData[0], pOp->op.au4OpData[1]);\r
+    /*wake up chip first*/\r
+    if (DISABLE_PSM_MONITOR()) {\r
+        WMT_ERR_FUNC("wake up failed\n");\r
+        wmt_lib_put_op_to_free_queue(pOp);\r
+        return -1;\r
+    }\r
+    bRet = wmt_lib_put_act_op(pOp);\r
+    ENABLE_PSM_MONITOR();\r
+    if ((cmd != WMTDRV_CMD_ASSERT) && (cmd != WMTDRV_CMD_EXCEPTION))\r
+    {\r
+        if (MTK_WCN_BOOL_FALSE == bRet)\r
+        {\r
+            gCoexBuf.availSize = 0;\r
+        }\r
+        else\r
+        {\r
+            gCoexBuf.availSize = pOp->op.au4OpData[3];\r
+            WMT_INFO_FUNC("gCoexBuf.availSize = %d\n", gCoexBuf.availSize);\r
+        }\r
+    }\r
+    //wmt_lib_host_awake_put();\r
+    WMT_INFO_FUNC("CMD_TEST, opid (%d), par(%d, %d), ret(%d), result(%s)\n", \\r
+    pOp->op.opId, \\r
+    pOp->op.au4OpData[0], \\r
+    pOp->op.au4OpData[1], \\r
+    bRet, \\r
+    MTK_WCN_BOOL_FALSE == bRet ? "failed" : "succeed"\\r
+    );\r
+    \r
+    return 0;\r
+}\r
+\r
+INT32 wmt_dbg_inband_rst(INT32 par1, INT32 par2, INT32 par3)\r
+{\r
+    if (0 == par2)\r
+    {\r
+        WMT_INFO_FUNC("inband reset test!!\n");\r
+        mtk_wcn_stp_inband_reset();\r
+       }\r
+    else\r
+    {\r
+        WMT_INFO_FUNC("STP context reset in host side!!\n");\r
+        mtk_wcn_stp_flush_context();\r
+    }\r
+    \r
+    return 0;\r
+}\r
+\r
+INT32 wmt_dbg_chip_rst(INT32 par1, INT32 par2, INT32 par3)\r
+{\r
+    if (0 == par2)\r
+    {\r
+        if (mtk_wcn_stp_is_ready())\r
+        {\r
+            WMT_INFO_FUNC("whole chip reset test\n");\r
+            wmt_lib_cmb_rst(WMTRSTSRC_RESET_TEST);\r
+        }\r
+        else\r
+        {\r
+            WMT_INFO_FUNC("STP not ready , not to launch whole chip reset test\n");\r
+        }\r
+    }\r
+    else if (1 == par2)\r
+    {\r
+        WMT_INFO_FUNC("chip hardware reset test\n");    \r
+        wmt_lib_hw_rst();\r
+    }\r
+    else\r
+    {\r
+        WMT_INFO_FUNC("chip software reset test\n");\r
+        wmt_lib_sw_rst(1);\r
+    }\r
+    return 0;\r
+}\r
+\r
+INT32 wmt_dbg_func_ctrl(INT32 par1, INT32 par2, INT32 par3)\r
+{\r
+    if (WMTDRV_TYPE_WMT > par2 || WMTDRV_TYPE_LPBK == par2)\r
+    {\r
+        if (0 == par3)\r
+        {\r
+            WMT_INFO_FUNC("function off test, type(%d)\n", par2);\r
+            mtk_wcn_wmt_func_off(par2);\r
+        }\r
+        else\r
+        {\r
+            WMT_INFO_FUNC("function on test, type(%d)\n", par2);\r
+            mtk_wcn_wmt_func_on(par2);\r
+        }\r
+    }\r
+    else\r
+    {\r
+        WMT_INFO_FUNC("function ctrl test, invalid type(%d)\n", par2);\r
+    }\r
+    return 0;    \r
+}\r
+\r
+INT32 wmt_dbg_raed_chipid(INT32 par1, INT32 par2, INT32 par3)\r
+{\r
+    WMT_INFO_FUNC("chip version = %d\n", wmt_lib_get_icinfo(WMTCHIN_MAPPINGHWVER));\r
+    return 0;\r
+}\r
+\r
+INT32 wmt_dbg_wmt_dbg_level(INT32 par1, INT32 par2, INT32 par3)\r
+{\r
+    par2 = (WMT_LOG_ERR <= par2 && WMT_LOG_LOUD >= par2) ? par2 : WMT_LOG_INFO;\r
+    wmt_lib_dbg_level_set(par2);\r
+    WMT_INFO_FUNC("set wmt log level to %d\n", par2);\r
+    return 0;\r
+}\r
+\r
+INT32 wmt_dbg_stp_dbg_level(INT32 par1, INT32 par2, INT32 par3)\r
+{\r
+    par2 = (0 <= par2 && 4 >= par2) ? par2 : 2;\r
+    mtk_wcn_stp_dbg_level(par2);\r
+    WMT_INFO_FUNC("set stp log level to %d\n", par2);\r
+    return 0;\r
+\r
+}\r
+\r
+INT32 wmt_dbg_reg_read(INT32 par1, INT32 par2, INT32 par3)\r
+{\r
+    //par2-->register address\r
+    //par3-->register mask\r
+    UINT32 value = 0x0;\r
+    UINT32 iRet = -1;\r
+#if 0    \r
+    DISABLE_PSM_MONITOR();\r
+    iRet = wmt_core_reg_rw_raw(0, par2, &value, par3);\r
+    ENABLE_PSM_MONITOR();\r
+#endif\r
+    iRet = wmt_lib_reg_rw(0, par2, &value, par3);\r
+    WMT_INFO_FUNC("read combo chip register (0x%08x) with mask (0x%08x) %s, value = 0x%08x\n", \\r
+        par2, \\r
+        par3, \\r
+        iRet != 0 ? "failed" : "succeed", \\r
+        iRet != 0 ?  -1: value\\r
+        );\r
+    return 0;\r
+}\r
+\r
+INT32 wmt_dbg_reg_write(INT32 par1, INT32 par2, INT32 par3)\r
+{\r
+    //par2-->register address    \r
+    //par3-->value to set\r
+    UINT32 iRet = -1;\r
+    #if 0\r
+    DISABLE_PSM_MONITOR();\r
+    iRet = wmt_core_reg_rw_raw(1, par2, &par3, 0xffffffff);\r
+    ENABLE_PSM_MONITOR();\r
+    #endif\r
+    iRet = wmt_lib_reg_rw(1, par2, &par3, 0xffffffff);\r
+    WMT_INFO_FUNC("write combo chip register (0x%08x) with value (0x%08x) %s\n", \\r
+        par2, \\r
+        par3, \\r
+        iRet != 0 ? "failed" : "succeed"\\r
+        );\r
+    return 0;\r
+}\r
+\r
+INT32 wmt_dbg_efuse_read(INT32 par1, INT32 par2, INT32 par3)\r
+{\r
+    //par2-->efuse address\r
+    //par3-->register mask\r
+    UINT32 value = 0x0;\r
+    UINT32 iRet = -1;\r
+\r
+    iRet = wmt_lib_efuse_rw(0, par2, &value, par3);\r
+    WMT_INFO_FUNC("read combo chip efuse (0x%08x) with mask (0x%08x) %s, value = 0x%08x\n", \\r
+        par2, \\r
+        par3, \\r
+        iRet != 0 ? "failed" : "succeed", \\r
+        iRet != 0 ?  -1: value\\r
+        );\r
+    return 0;\r
+}\r
+\r
+INT32 wmt_dbg_efuse_write(INT32 par1, INT32 par2, INT32 par3)\r
+{\r
+    //par2-->efuse address    \r
+    //par3-->value to set\r
+    UINT32 iRet = -1;\r
+    iRet = wmt_lib_efuse_rw(1, par2, &par3, 0xffffffff);\r
+    WMT_INFO_FUNC("write combo chip efuse (0x%08x) with value (0x%08x) %s\n", \\r
+        par2, \\r
+        par3, \\r
+        iRet != 0 ? "failed" : "succeed"\\r
+        );\r
+    return 0;\r
+}\r
+\r
+\r
+INT32 wmt_dbg_sdio_ctrl(INT32 par1, INT32 par2, INT32 par3)\r
+{\r
+    INT32 iRet = -1;\r
+    iRet = wmt_lib_sdio_ctrl (0 != par2 ? 1 : 0);\r
+    WMT_INFO_FUNC("ctrl SDIO function %s\n", 0 == iRet ? "succeed" : "failed");\r
+    return 0;\r
+}\r
+\r
+\r
+INT32 wmt_dbg_stp_dbg_ctrl(INT32 par1, INT32 par2, INT32 par3)\r
+{\r
+    if (1 < par2)\r
+    {\r
+        mtk_wcn_stp_dbg_dump_package();\r
+        return 0;\r
+    }\r
+    WMT_INFO_FUNC("%s stp debug function\n", 0 == par2 ? "disable" : "enable");\r
+    if (0 == par2)\r
+    {\r
+        mtk_wcn_stp_dbg_disable();\r
+    }\r
+    else if (1 == par2)\r
+    {\r
+        mtk_wcn_stp_dbg_enable();\r
+    }\r
+    return 0;\r
+}\r
+\r
+INT32 wmt_dbg_stp_dbg_log_ctrl(INT32 par1, INT32 par2, INT32 par3)\r
+{\r
+    mtk_wcn_stp_dbg_log_ctrl(0 != par2 ? 1 : 0);\r
+    return 0;\r
+}\r
+\r
+\r
+\r
+INT32 wmt_dbg_wmt_assert_ctrl(INT32 par1, INT32 par2, INT32 par3)\r
+{\r
+    mtk_wcn_stp_coredump_flag_ctrl(0 != par2 ? 1 : 0);\r
+    return 0;\r
+}\r
+\r
+\r
+INT32 wmt_dbg_coex_test(INT32 par1, INT32 par2, INT32 par3)\r
+{\r
+    WMT_INFO_FUNC("coexistance test cmd!!\n");\r
+    return wmt_dbg_cmd_test_api(par2 + WMTDRV_CMD_COEXDBG_00);\r
+}\r
+\r
+INT32 wmt_dbg_rst_ctrl(INT32 par1, INT32 par2, INT32 par3)\r
+{\r
+    WMT_INFO_FUNC("%s audo rst\n", 0 == par2 ? "disable" : "enable");\r
+    mtk_wcn_stp_set_auto_rst(0 == par2 ? 0 : 1);\r
+    return 0;\r
+}\r
+\r
+static INT32 wmt_dev_dbg_read(CHAR *page, CHAR **start, off_t off, INT32 count, INT32 *eof, void *data){\r
+    INT32 len = 0;\r
+\r
+    if(off > 0){\r
+        len = 0;\r
+    } else {\r
+        /*len = sprintf(page, "%d\n", g_psm_enable);*/\r
+        if ( gCoexBuf.availSize <= 0)\r
+        {\r
+            WMT_INFO_FUNC("no data available, please run echo 15 xx > /proc/driver/wmt_psm first\n");\r
+            len = osal_sprintf(page, "no data available, please run echo 15 xx > /proc/driver/wmt_psm first\n");\r
+        }\r
+        else\r
+        {\r
+            INT32 i = 0;\r
+            /*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*/\r
+            for (i = 0; i < gCoexBuf.availSize; i++)\r
+            {\r
+                len += osal_sprintf(page + len, "0x%02x ", gCoexBuf.buffer[i]);\r
+            }\r
+            len += osal_sprintf(page + len, "\n");\r
+        }\r
+    }\r
+    gCoexBuf.availSize = 0;\r
+    return len;\r
+}\r
+\r
+INT32 wmt_dbg_ut_test(INT32 par1, INT32 par2, INT32 par3)\r
+{\r
+\r
+    INT32 i = 0;\r
+    INT32 j = 0;\r
+    INT32 iRet = 0;\r
+   \r
+    i = 20;          \r
+    while((i--) > 0){\r
+        WMT_INFO_FUNC("#### UT WMT and STP Function On/Off .... %d\n", i);\r
+        j = 10;\r
+        while((j--) > 0){\r
+            WMT_INFO_FUNC("#### BT  On .... (%d, %d) \n", i, j);\r
+            iRet = mtk_wcn_wmt_func_on(WMTDRV_TYPE_BT); \r
+            if(iRet == MTK_WCN_BOOL_FALSE){\r
+                break;\r
+            }\r
+            WMT_INFO_FUNC("#### GPS On .... (%d, %d) \n", i, j);\r
+            iRet = mtk_wcn_wmt_func_on(WMTDRV_TYPE_GPS); \r
+            if(iRet == MTK_WCN_BOOL_FALSE){\r
+                break;\r
+            }\r
+            WMT_INFO_FUNC("#### FM  On .... (%d, %d) \n", i, j);\r
+            iRet = mtk_wcn_wmt_func_on(WMTDRV_TYPE_FM);\r
+            if(iRet == MTK_WCN_BOOL_FALSE){\r
+                break;\r
+            }\r
+            WMT_INFO_FUNC("#### WIFI On .... (%d, %d) \n", i, j);\r
+            iRet = mtk_wcn_wmt_func_on(WMTDRV_TYPE_WIFI); \r
+            if(iRet == MTK_WCN_BOOL_FALSE){\r
+                break;\r
+            }\r
+            WMT_INFO_FUNC("#### BT  Off .... (%d, %d) \n", i, j);\r
+            iRet = mtk_wcn_wmt_func_off(WMTDRV_TYPE_BT); \r
+            if(iRet == MTK_WCN_BOOL_FALSE){\r
+                break;\r
+            }\r
+            WMT_INFO_FUNC("#### GPS  Off ....(%d, %d) \n", i, j);\r
+            iRet = mtk_wcn_wmt_func_off(WMTDRV_TYPE_GPS); \r
+            if(iRet == MTK_WCN_BOOL_FALSE){\r
+                break;\r
+            }\r
+            WMT_INFO_FUNC("#### FM  Off .... (%d, %d) \n", i, j);\r
+            iRet = mtk_wcn_wmt_func_off(WMTDRV_TYPE_FM); \r
+            if(iRet == MTK_WCN_BOOL_FALSE){\r
+                break;\r
+            }\r
+            WMT_INFO_FUNC("#### WIFI  Off ....(%d, %d) \n", i, j);\r
+            iRet = mtk_wcn_wmt_func_off(WMTDRV_TYPE_WIFI);           \r
+            if(iRet == MTK_WCN_BOOL_FALSE){\r
+                break;\r
+            }\r
+        }\r
+        if(iRet == MTK_WCN_BOOL_FALSE){\r
+                break;\r
+        }          \r
+    }\r
+    if(iRet == MTK_WCN_BOOL_FALSE){\r
+        WMT_INFO_FUNC("#### UT FAIL!!\n");\r
+    } else {\r
+        WMT_INFO_FUNC("#### UT PASS!!\n");\r
+    }\r
+    return iRet;        \r
+}\r
+\r
+\r
+static INT32 wmt_dev_dbg_write(struct file *file, const CHAR *buffer, ULONG count, void *data){\r
+    \r
+    CHAR buf[256];\r
+    CHAR *pBuf;\r
+    ULONG len = count;\r
+    INT32 x = 0,y = 0, z=0;\r
+    CHAR *pToken = NULL;\r
+    CHAR *pDelimiter = " \t";\r
+\r
+    WMT_INFO_FUNC("write parameter len = %d\n\r", (INT32)len);\r
+    if(len >= osal_sizeof(buf)){\r
+        WMT_ERR_FUNC("input handling fail!\n");\r
+        len = osal_sizeof(buf) - 1;\r
+        return -1;\r
+    }    \r
+    \r
+    if(copy_from_user(buf, buffer, len)){\r
+        return -EFAULT;\r
+    }\r
+    buf[len] = '\0';\r
+    WMT_INFO_FUNC("write parameter data = %s\n\r", buf);\r
+\r
+    pBuf = buf;\r
+    pToken = osal_strsep(&pBuf, pDelimiter);\r
+    x = NULL != pToken ? osal_strtol(pToken, NULL, 16) : 0; \r
+\r
+    pToken = osal_strsep(&pBuf, "\t\n ");\r
+    if(pToken != NULL){\r
+        y = osal_strtol(pToken, NULL, 16);\r
+        WMT_INFO_FUNC("y = 0x%08x \n\r", y);\r
+    } else {\r
+        y = 3000;\r
+         /*efuse, register read write default value*/\r
+        if(0x11 == x || 0x12 == x || 0x13 == x) {\r
+            y = 0x80000000;\r
+        }\r
+    }\r
+\r
+    pToken = osal_strsep(&pBuf, "\t\n ");\r
+    if(pToken != NULL){\r
+        z = osal_strtol(pToken, NULL, 16);\r
+    } else {\r
+        z = 10;\r
+        /*efuse, register read write default value*/\r
+        if(0x11 == x || 0x12 == x || 0x13 == x) {\r
+            z = 0xffffffff;\r
+        }\r
+    }\r
+    \r
+    WMT_INFO_FUNC("x(0x%08x), y(0x%08x), z(0x%08x)\n\r", x, y, z);\r
+\r
+    if (osal_array_size(wmt_dev_dbg_func) > x && NULL != wmt_dev_dbg_func[x])\r
+    {\r
+        (*wmt_dev_dbg_func[x])(x, y, z);\r
+    }\r
+    else\r
+    {\r
+        WMT_WARN_FUNC("no handler defined for command id(0x%08x)\n\r", x);\r
+    }\r
+    return len;\r
+}\r
+\r
+INT32 wmt_dev_dbg_setup(VOID)\r
+{\r
+    gWmtDbgEntry = create_proc_entry(WMT_DBG_PROCNAME, 0664, NULL);\r
+    if(gWmtDbgEntry == NULL){\r
+        WMT_ERR_FUNC("Unable to create /proc entry\n\r");\r
+        return -1;\r
+    }\r
+    gWmtDbgEntry->read_proc = wmt_dev_dbg_read;\r
+    gWmtDbgEntry->write_proc = wmt_dev_dbg_write;\r
+    return 0;\r
+}\r
+\r
+INT32 wmt_dev_dbg_remove(VOID)\r
+{\r
+    if (NULL != gWmtDbgEntry)\r
+    {\r
+        remove_proc_entry(WMT_DBG_PROCNAME, NULL);\r
+    }\r
+#if CFG_WMT_PS_SUPPORT\r
+    wmt_lib_ps_deinit();\r
+#endif\r
+    return 0;\r
+}\r
+#endif\r
+\r
diff --git a/drivers/mtk_wcn_combo/common/core/wmt_exp.c b/drivers/mtk_wcn_combo/common/core/wmt_exp.c
new file mode 100755 (executable)
index 0000000..915d882
--- /dev/null
@@ -0,0 +1,414 @@
+/*! \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 <wmt_exp.h>
+#include <wmt_lib.h>
+#include <hif_sdio.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
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                  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;
+    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\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();
+    
+    if (MTK_WCN_BOOL_FALSE == bRet) {
+        WMT_WARN_FUNC("OPID(%d) type(%d) fail\n",
+            pOp->op.opId,
+            pOp->op.au4OpData[0]);
+    }
+    else {
+        WMT_INFO_FUNC("OPID(%d) type(%d) ok\n",
+            pOp->op.opId,
+            pOp->op.au4OpData[0]);
+    }
+    return bRet;
+}
+
+MTK_WCN_BOOL
+mtk_wcn_wmt_func_off (
+    ENUM_WMTDRV_TYPE_T type
+    )
+{
+    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;
+}
+
+MTK_WCN_BOOL
+mtk_wcn_wmt_func_on (
+    ENUM_WMTDRV_TYPE_T type
+    )
+{
+    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;
+}
+
+/*
+return value:
+enable/disable thermal sensor function: true(1)/false(0)
+read thermal sensor function:thermal value
+
+*/
+INT8
+mtk_wcn_wmt_therm_ctrl (
+    ENUM_WMTTHERM_TYPE_T eType
+    )
+{
+    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\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("OPID(%d) type(%d) fail\n\n",
+            pOpData->opId,
+            pOpData->au4OpData[0]);
+        /*0xFF means read error occurs*/
+        pOpData->au4OpData[1] = (eType == WMTTHERM_READ) ? 0xFF : MTK_WCN_BOOL_FALSE;/*will return to function driver*/
+    }
+    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];
+}
+
+ENUM_WMTHWVER_TYPE_T
+mtk_wcn_wmt_hwver_get (VOID)
+{
+    // 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);
+}
+
+MTK_WCN_BOOL
+mtk_wcn_wmt_dsns_ctrl (
+    ENUM_WMTDSNS_TYPE_T eType
+    )
+{
+    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\n");
+        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;
+}
+
+INT32
+mtk_wcn_wmt_msgcb_reg (
+    ENUM_WMTDRV_TYPE_T eType,
+    PF_WMT_CB pCb
+    )
+{
+    return (INT32)wmt_lib_msgcb_reg(eType, pCb);
+}
+
+INT32
+mtk_wcn_wmt_msgcb_unreg (
+    ENUM_WMTDRV_TYPE_T eType
+    )
+{
+    return (INT32)wmt_lib_msgcb_unreg(eType);
+}
+
+INT32
+mtk_wcn_stp_wmt_sdio_op_reg (
+    PF_WMT_SDIO_PSOP own_cb
+    )
+{
+    wmt_lib_ps_set_sdio_psop(own_cb);
+    return 0;
+}
+
+
+INT32 
+mtk_wcn_stp_wmt_sdio_host_awake(
+    VOID
+    )
+{    
+    wmt_lib_ps_irq_cb();
+    return 0;
+}
+
+MTK_WCN_BOOL mtk_wcn_wmt_assert (
+    void
+    )
+{
+    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();
+    pOp->op.au4OpData[0] = 0;
+    
+    /*wake up chip first*/
+    if (DISABLE_PSM_MONITOR()) {
+        WMT_ERR_FUNC("wake up failed\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;
+}
+
+extern INT32 mtk_wcn_wmt_chipid_query (VOID)
+{
+    return mtk_wcn_hif_sdio_query_chipid(0);
+}
+
+
+
+EXPORT_SYMBOL(mtk_wcn_wmt_assert);
+EXPORT_SYMBOL(mtk_wcn_stp_wmt_sdio_host_awake);
+EXPORT_SYMBOL(mtk_wcn_stp_wmt_sdio_op_reg);
+EXPORT_SYMBOL(mtk_wcn_wmt_msgcb_unreg);
+EXPORT_SYMBOL(mtk_wcn_wmt_msgcb_reg);
+EXPORT_SYMBOL(mtk_wcn_wmt_dsns_ctrl);
+EXPORT_SYMBOL(mtk_wcn_wmt_hwver_get);
+EXPORT_SYMBOL(mtk_wcn_wmt_therm_ctrl);
+EXPORT_SYMBOL(mtk_wcn_wmt_func_on);
+EXPORT_SYMBOL(mtk_wcn_wmt_func_off);
+EXPORT_SYMBOL(mtk_wcn_wmt_chipid_query);
+
+
diff --git a/drivers/mtk_wcn_combo/common/core/wmt_func.c b/drivers/mtk_wcn_combo/common/core/wmt_func.c
new file mode 100755 (executable)
index 0000000..cf71766
--- /dev/null
@@ -0,0 +1,510 @@
+/*! \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"
+
+
+
+/*******************************************************************************
+*                              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 = ~(0x1UL << 5),
+        .regMask = 0x00000020UL,    
+    },
+    {
+        //pull up ctrl register
+        .regAddr = 0x80050000,
+        .regValue = 0x1UL << 5,
+        .regMask = 0x00000020UL,    
+    },
+    {
+         //iomode ctrl register
+        .regAddr = 0x80050110,
+        .regValue = 0x1UL << 0,
+        .regMask = 0x00000007UL,    
+    },
+    {
+        //output high/low ctrl register
+        .regAddr = 0x80050040,
+        .regValue = 0x1UL << 5,
+        .regMask = 0x00000020UL,    
+    }
+
+};
+CMB_PIN_CTRL_REG eediPinOlRegs[] = {
+    {
+        .regAddr = 0x80050020,
+        .regValue = 0x1UL << 5,
+        .regMask = 0x00000020UL,    
+    },
+    {
+        .regAddr = 0x80050000,
+        .regValue = ~(0x1UL << 5),
+        .regMask = 0x00000020UL,    
+    },
+    {
+        .regAddr = 0x80050110,
+        .regValue = 0x1UL << 0,
+        .regMask = 0x00000007UL,    
+    },
+    {
+        .regAddr = 0x80050040,
+        .regValue = ~(0x1UL << 5),
+        .regMask = 0x00000020UL,    
+    }
+};
+
+CMB_PIN_CTRL_REG eedoPinOhRegs[] = 
+{
+    {
+        .regAddr = 0x80050020,
+        .regValue = ~(0x1UL << 7),
+        .regMask = 0x00000080UL,    
+    },
+    {
+        .regAddr = 0x80050000,
+        .regValue = 0x1UL << 7,
+        .regMask = 0x00000080UL,    
+    },
+    {
+        .regAddr = 0x80050110,
+        .regValue = 0x1UL << 12,
+        .regMask = 0x00007000UL,    
+    },
+    {
+        .regAddr = 0x80050040,
+        .regValue = 0x1UL << 7,
+        .regMask = 0x00000080UL,    
+    }
+};
+
+
+CMB_PIN_CTRL_REG eedoPinOlRegs[] = 
+{
+    {
+        .regAddr = 0x80050020,
+        .regValue = 0x1UL << 7,
+        .regMask = 0x00000080UL,    
+    },
+    {
+        .regAddr = 0x80050000,
+        .regValue = ~(0x1UL << 7),
+        .regMask = 0x00000080UL,    
+    },
+    {
+        .regAddr = 0x80050110,
+        .regValue = 0x1UL << 12,
+        .regMask = 0x00007000UL,    
+    },
+    {
+        .regAddr = 0x80050040,
+        .regValue = ~(0x1UL << 7),
+        .regMask = 0x00000080UL,    
+    }        
+    
+};
+
+CMB_PIN_CTRL_REG gsyncPinOnRegs[] = 
+{
+    {
+        .regAddr = 0x80050110,
+        .regValue = 0x3UL << 20,
+        .regMask = 0x7UL << 20,
+    }
+
+};
+
+CMB_PIN_CTRL_REG gsyncPinOffRegs[] = 
+{
+    {
+        .regAddr = 0x80050110,
+        .regValue = 0x0UL << 20,
+        .regMask = 0x7UL << 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);
+    return wmt_core_func_ctrl_cmd(WMTDRV_TYPE_BT, MTK_WCN_BOOL_TRUE);
+}
+
+INT32 wmt_func_bt_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf)
+{
+    //return wmt_func_bt_ctrl(FUNC_OFF);
+    return wmt_core_func_ctrl_cmd(WMTDRV_TYPE_BT, MTK_WCN_BOOL_FALSE);
+}
+
+#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;
+    UINT32 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;
+    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;
+    }
+    else {
+        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++)
+        {
+            pReg = FUNC_ON == funcStatus ? &pCmbPinCtrl->pFuncOnArray[i] : &pCmbPinCtrl->pFuncOffArray[i];
+            regAddr = pReg->regAddr;
+            regValue = pReg->regValue;
+            regMask = pReg->regMask;
+            
+            iRet = wmt_core_reg_rw_raw(1, regAddr, &regValue, 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;
+            }
+            else {
+                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++)
+                {
+                    pReg = FUNC_ON == funcStatus ? &pCmbPinCtrl->pFuncOnArray[i] : &pCmbPinCtrl->pFuncOffArray[i];
+                    regAddr = pReg->regAddr;
+                    regValue = pReg->regValue;
+                    regMask = pReg->regMask;
+                
+                    iRet = wmt_core_reg_rw_raw(1, regAddr, &regValue, 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;
+    iRet = wmt_func_gps_pre_on(pOps, pConf);
+    if (0 == iRet)
+    {
+        iRet = wmt_func_gps_ctrl(FUNC_ON);
+    }
+    return iRet;
+}
+
+INT32 wmt_func_gps_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf)
+{
+    INT32 iRet = 0;
+    iRet = wmt_func_gps_pre_off(pOps, pConf);
+    if (0 == iRet)
+    {
+        iRet = wmt_func_gps_ctrl(FUNC_OFF);
+    }
+    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);
+    return wmt_core_func_ctrl_cmd(WMTDRV_TYPE_FM, MTK_WCN_BOOL_TRUE);
+}
+
+INT32 wmt_func_fm_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf)
+{
+    //return wmt_func_fm_ctrl(FUNC_OFF);
+    return wmt_core_func_ctrl_cmd(WMTDRV_TYPE_FM, MTK_WCN_BOOL_FALSE);
+}
+
+#endif
+
+#if CFG_FUNC_WIFI_SUPPORT
+
+INT32
+wmt_func_wifi_ctrl (
+    ENUM_FUNC_STATE funcState
+    )
+{
+    INT32 iRet = 0;
+    UINT32 ctrlPa1 = WMT_SDIO_FUNC_WIFI;
+    UINT32 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;
+}
+
+
+INT32 wmt_func_wifi_on(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf)
+{
+    return wmt_func_wifi_ctrl(FUNC_ON);
+}
+
+INT32 wmt_func_wifi_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf)
+{
+    return wmt_func_wifi_ctrl(FUNC_OFF);
+}
+#endif
+
diff --git a/drivers/mtk_wcn_combo/common/core/wmt_ic_6620.c b/drivers/mtk_wcn_combo/common/core/wmt_ic_6620.c
new file mode 100755 (executable)
index 0000000..fe029aa
--- /dev/null
@@ -0,0 +1,1906 @@
+/*! \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]"
+
+
+/*******************************************************************************
+*                    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 MT6620E2_PATCH_FRAG_SIZE (900)
+#define WMT_PATCH_FRAG_1ST (0x1)
+#define WMT_PATCH_FRAG_MID (0x2)
+#define WMT_PATCH_FRAG_LAST (0x3)
+
+#define CFG_CHECK_WMT_RESULT (1)
+#define CFG_WMT_BT_PORT2 (0) /* BT Port 2 Feature. this command does not need after coex command is downconfirmed by LC,*/
+
+#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_WMT_COREDUMP_ENABLE 0
+
+#define CFG_WMT_MULTI_PATCH (1)
+/*******************************************************************************
+*                             D A T A   T Y P E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                           P R I V A T E   D A T A
+********************************************************************************
+*/
+#if !(CFG_WMT_MULTI_PATCH)
+static UCHAR gDefPatchName[NAME_MAX + 1];
+#endif
+static UCHAR gFullPatchName[NAME_MAX + 1];
+static const WMT_IC_INFO_S *gp_mt6620_info = NULL;
+
+static UCHAR WMT_WAKEUP_DIS_GATE_CMD[] = {0x1, 0x3, 0x01, 0x00, 0x04};
+static UCHAR WMT_WAKEUP_DIS_GATE_EVT[] = {0x2, 0x3, 0x02, 0x0, 0x0, 0x04};
+#if 0
+static UCHAR WMT_WAKEUP_EN_GATE_CMD[] = {0x1, 0x3, 0x01, 0x00, 0x05};
+static UCHAR WMT_WAKEUP_EN_GATE_EVT[] = {0x2, 0x3, 0x02, 0x0, 0x0, 0x05};
+#endif
+static UCHAR WMT_QUERY_BAUD_CMD[] = {0x01, 0x04, 0x01, 0x00, 0x02};
+static UCHAR WMT_QUERY_BAUD_EVT_115200[] = {0x02, 0x04, 0x06, 0x00, 0x00, 0x02, 0x00, 0xC2, 0x01, 0x00};
+static UCHAR WMT_QUERY_BAUD_EVT_X[] = {0x02, 0x04, 0x06, 0x00, 0x00, 0x02, 0xAA, 0xAA, 0xAA, 0xBB};
+static UCHAR WMT_QUERY_STP_CMD[] = {0x01, 0x04, 0x01, 0x00, 0x04};
+static UCHAR WMT_QUERY_STP_EVT_DEFAULT[] = {0x02, 0x04, 0x06, 0x00, 0x00, 0x04, 0x11, 0x00, 0x00, 0x00};
+static UCHAR WMT_QUERY_STP_EVT_UART[] = {0x02, 0x04, 0x06, 0x00, 0x00, 0x04, 0xDF, 0x0E, 0x68, 0x01};
+static UCHAR WMT_SET_BAUD_CMD_X[] = {0x01, 0x04, 0x05, 0x00, 0x01, 0xAA, 0xAA, 0xAA, 0xBB};
+static UCHAR WMT_SET_BAUD_EVT[] = {0x02, 0x04, 0x02, 0x00, 0x00, 0x01};
+static UCHAR WMT_SET_WAKEUP_WAKE_CMD_RAW[] = {0xFF};
+static UCHAR WMT_SET_WAKEUP_WAKE_EVT[] = {0x02, 0x03, 0x02, 0x00, 0x00, 0x03};
+#if CFG_WMT_MULTI_PATCH
+static UCHAR WMT_PATCH_ADDRESS_CMD[] = {0x01,0x08,0x10,0x00,0x01,0x01,0x00,0x01,0x64,0x0E,0x00,0x01,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff};
+static UCHAR WMT_PATCH_ADDRESS_EVT[] = {0x02,0x08,0x04,0x00,0x00,0x00,0x00,0x01};
+static UCHAR WMT_PATCH_P_ADDRESS_CMD[] = {0x01,0x08,0x10,0x00,0x01,0x01,0x00,0x01,0x38,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff};
+static UCHAR WMT_PATCH_P_ADDRESS_EVT[] = {0x02,0x08,0x04,0x00,0x00,0x00,0x00,0x01};
+#endif
+
+static UCHAR WMT_PATCH_CMD[] = {0x01, 0x01, 0x00, 0x00, 0x00};
+static UCHAR WMT_PATCH_EVT[] = {0x02, 0x01, 0x01, 0x00, 0x00};
+static UCHAR WMT_RESET_CMD[] = {0x01, 0x07, 0x01, 0x00, 0x04};
+static UCHAR WMT_RESET_EVT[] = {0x02, 0x07, 0x01, 0x00, 0x00};
+#if CFG_WMT_BT_PORT2
+static UCHAR WMT_BTP2_CMD[] = {0x01, 0x10, 0x03, 0x00, 0x01, 0x03, 0x01};
+static UCHAR WMT_BTP2_EVT[] = {0x02, 0x10, 0x01, 0x00, 0x00};
+#endif
+/*coex cmd/evt++*/
+static UCHAR WMT_COEX_SETTING_CONFIG_CMD[] = {0x01, 0x10, 0x04, 0x00, 0x01, 0xAA, 0xBB, 0xCC};
+static UCHAR WMT_COEX_SETTING_CONFIG_EVT[] = {0x02, 0x10, 0x01, 0x00, 0x00};
+static UCHAR WMT_BT_COEX_SETTING_CONFIG_CMD[] = {0x01, 0x10, 0x0B,
+                                                         0x00, 0x02,
+                                                         0x00, 0x00, 0x00, 0x00,
+                                                         0xBB,0xCC,0xDD,0xEE,0xFF,0xAA};
+static UCHAR WMT_BT_COEX_SETTING_CONFIG_EVT[] = {0x02, 0x10, 0x01, 0x00, 0x00};
+static UCHAR WMT_WIFI_COEX_SETTING_CONFIG_CMD[] = {0x01, 0x10, 0x0C,
+                                                           0x00, 0x03,
+                                                           0x00, 0x00,0x00,0x00,0x00,
+                                                           0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0xAA};
+static UCHAR WMT_WIFI_COEX_SETTING_CONFIG_EVT[] = {0x02, 0x10, 0x01, 0x00, 0x00};
+static UCHAR WMT_PTA_COEX_SETTING_CONFIG_CMD[] = {0x01, 0x10, 0x0A,
+                                                          0x00, 0x04,
+                                                          0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xEE, 0xFF, 0xFF, 0xFE};
+static UCHAR WMT_PTA_COEX_SETTING_CONFIG_EVT[] = {0x02, 0x10, 0x01, 0x00, 0x00};
+static UCHAR WMT_MISC_COEX_SETTING_CONFIG_CMD[] = {0x01, 0x10, 0x09,
+                                                           0x00, 0x05,
+                                                           0xAA, 0xAA, 0xAA, 0xAA,
+                                                           0xBB, 0xBB, 0xBB, 0xBB};
+static UCHAR WMT_MISC_COEX_SETTING_CONFIG_EVT[] = {0x02, 0x10, 0x01, 0x00, 0x00};
+/*coex cmd/evt--*/
+static UCHAR WMT_SET_STP_CMD[] = {0x01, 0x04, 0x05, 0x00, 0x03, 0xDF, 0x0E, 0x68, 0x01};
+static UCHAR WMT_SET_STP_EVT[] = {0x02, 0x04, 0x02, 0x00, 0x00, 0x03};
+static UCHAR WMT_STRAP_CONF_CMD_FM_COMM[] = {0x01, 0x05, 0x02, 0x00, 0x02, 0x02};
+static UCHAR WMT_STRAP_CONF_EVT[] = {0x02, 0x05, 0x02, 0x00, 0x00, 0x02};
+#if 0
+static UCHAR WMT_SET_OSC32K_BYPASS_CMD[]= {0x01, 0x0A, 0x01, 0x00, 0x05};
+static UCHAR WMT_SET_OSC32K_BYPASS_EVT[]= {0x02, 0x0A, 0x01, 0x00, 0x00};
+#endif
+
+static UCHAR  WMT_CORE_DUMP_LEVEL_04_CMD[] = {0x1, 0x0F, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static UCHAR  WMT_CORE_DUMP_LEVEL_04_EVT[] = {0x2, 0x0F, 0x01, 0x00, 0x00};
+
+/* enable all interrupt */
+static UCHAR 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 UCHAR WMT_SET_ALLINT_REG_EVT[] = {0x02, 0x08, 0x04, 0x00/*length*/
+    ,0x00 /*S: 0*/
+    ,0x00 /*type: reg */
+    ,0x00 /*rev*/
+    ,0x01 /*1 registers*/
+};
+
+#if CFG_SET_OPT_REG_SWLA /* enable swla: eesk(7) eecs(8) oscen(19) sck0(24) scs0(25)  */
+static UCHAR 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 UCHAR 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 UCHAR 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 UCHAR 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 UCHAR 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 UCHAR 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 UCHAR 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 UCHAR 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 UCHAR 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 UCHAR WMT_SET_MCUIRQ_REG_EVT[] = {0x02, 0x08, 0x04, 0x00/*length*/
+    ,0x00 /* S: 0 */
+    ,0x00 /* type: reg */
+    ,0x00 /* rev */
+    ,0x05 /* 5 registers */
+};
+#endif
+#endif
+
+/* 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"),
+    /* only applied to MT6620 E1/E2? */
+    INIT_CMD(WMT_WAKEUP_DIS_GATE_CMD, WMT_WAKEUP_DIS_GATE_EVT, "disable gating"),
+};
+
+
+static struct init_script init_table_1_2[] =
+{
+    INIT_CMD(WMT_QUERY_BAUD_CMD, WMT_QUERY_BAUD_EVT_115200, "query baud 115200"),
+    INIT_CMD(WMT_QUERY_STP_CMD, WMT_QUERY_STP_EVT_DEFAULT, "query stp default"),
+    INIT_CMD(WMT_SET_BAUD_CMD_X, WMT_SET_BAUD_EVT, "set baud rate"),
+};
+
+static struct init_script init_table_2[] =
+{
+    INIT_CMD(WMT_QUERY_BAUD_CMD, WMT_QUERY_BAUD_EVT_X, "query baud X"),
+};
+
+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 0
+static struct init_script init_table_3_1[] =
+{
+    INIT_CMD(WMT_WAKEUP_EN_GATE_CMD, WMT_WAKEUP_EN_GATE_EVT, "ensable gating"),
+};
+#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_UART, "query stp uart"),
+    INIT_CMD(WMT_QUERY_BAUD_CMD, WMT_QUERY_BAUD_EVT_X, "query baud X"),
+};
+
+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[] =
+{
+#if 0
+    INIT_CMD(WMT_SET_OSC32K_BYPASS_CMD, WMT_SET_OSC32K_BYPASS_EVT, "set OSC32k by pass mode."),
+#endif
+       INIT_CMD(WMT_CORE_DUMP_LEVEL_04_CMD,WMT_CORE_DUMP_LEVEL_04_EVT,"setup core dump level"),
+};
+
+#if defined(CFG_SET_OPT_REG) && 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"),
+     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"),
+};
+
+/* MT6620 Chip Version and Info Table */
+static const WMT_IC_INFO_S mt6620_info_table[] = {
+    {
+        .u4HwVer            = 0x8A00,
+        .cChipName         = WMT_IC_NAME_MT6620,
+        .cChipVersion      = WMT_IC_VER_E1,
+        .cPatchNameExt     = WMT_IC_PATCH_NO_EXT,
+        .eWmtHwVer        = WMTHWVER_MT6620_E1,
+        .bWorkWithoutPatch = MTK_WCN_BOOL_FALSE,
+        .bPsmSupport       = MTK_WCN_BOOL_FALSE,
+    },
+    {
+        .u4HwVer            = 0x8A01,
+        .cChipName         = WMT_IC_NAME_MT6620,
+        .cChipVersion      = WMT_IC_VER_E2,
+        .cPatchNameExt     = WMT_IC_PATCH_NO_EXT,
+        .eWmtHwVer        = WMTHWVER_MT6620_E2,
+        .bWorkWithoutPatch = MTK_WCN_BOOL_FALSE,
+        .bPsmSupport       = MTK_WCN_BOOL_FALSE,
+    },
+    {
+        .u4HwVer            = 0x8A10,
+        .cChipName         = WMT_IC_NAME_MT6620,
+        .cChipVersion      = WMT_IC_VER_E3,
+        .cPatchNameExt     = WMT_IC_PATCH_E3_EXT,
+        .eWmtHwVer        = WMTHWVER_MT6620_E3,
+        .bWorkWithoutPatch = MTK_WCN_BOOL_FALSE,
+        .bPsmSupport       = MTK_WCN_BOOL_TRUE,
+    },
+    {
+        .u4HwVer            = 0x8A11,
+        .cChipName         = WMT_IC_NAME_MT6620,
+        .cChipVersion      = WMT_IC_VER_E4,
+        .cPatchNameExt     = WMT_IC_PATCH_E3_EXT,
+        .eWmtHwVer        = WMTHWVER_MT6620_E4,
+        .bWorkWithoutPatch = MTK_WCN_BOOL_FALSE,
+        .bPsmSupport       = MTK_WCN_BOOL_TRUE,
+    },
+    {
+        .u4HwVer            = 0x8A30,
+        .cChipName         = WMT_IC_NAME_MT6620,
+        .cChipVersion      = WMT_IC_VER_E6,
+        .cPatchNameExt     = WMT_IC_PATCH_E6_EXT,
+        .eWmtHwVer        = WMTHWVER_MT6620_E6,
+        .bWorkWithoutPatch = MTK_WCN_BOOL_TRUE /*MTK_WCN_BOOL_FALSE*/,
+        .bPsmSupport       = MTK_WCN_BOOL_TRUE,
+    },
+    {
+        .u4HwVer            = 0x8B30,
+        .cChipName         = WMT_IC_NAME_MT6620,
+        .cChipVersion      = WMT_IC_VER_E6,
+        .cPatchNameExt     = WMT_IC_PATCH_E6_EXT,
+        .eWmtHwVer        = WMTHWVER_MT6620_E6,
+        .bWorkWithoutPatch = MTK_WCN_BOOL_TRUE /*MTK_WCN_BOOL_FALSE*/,
+        .bPsmSupport       = MTK_WCN_BOOL_TRUE,
+    },
+    {
+        .u4HwVer            = 0x8B31,
+        .cChipName         = WMT_IC_NAME_MT6620,
+        .cChipVersion      = WMT_IC_VER_E7,
+        .cPatchNameExt     = WMT_IC_PATCH_E6_EXT,
+        .eWmtHwVer        = WMTHWVER_MT6620_E7,
+        .bWorkWithoutPatch = MTK_WCN_BOOL_TRUE /*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
+mt6620_sw_init (
+    P_WMT_HIF_CONF pWmtHifConf
+    );
+
+static INT32
+mt6620_sw_deinit (
+    P_WMT_HIF_CONF pWmtHifConf
+    );
+
+static INT32
+mt6620_pin_ctrl (
+    WMT_IC_PIN_ID id,
+    WMT_IC_PIN_STATE state,
+    UINT32 flag
+    );
+
+static INT32
+mt6620_aif_ctrl (
+    WMT_IC_PIN_STATE state,
+    UINT32 flag
+    );
+
+static INT32
+mt6620_ver_check (VOID);
+
+static const WMT_IC_INFO_S*
+mt6620_find_wmt_ic_info (
+    const UINT32 hw_ver
+    );
+
+static INT32
+wmt_stp_init_coex (VOID);
+
+#if CFG_WMT_MULTI_PATCH
+static INT32
+mt6620_patch_dwn (UINT32 index);
+static INT32 mt6620_patch_info_prepare(VOID);
+#else
+static INT32
+mt6620_update_patch_name (VOID);
+
+static INT32
+mt6620_patch_dwn (VOID);
+#endif
+static MTK_WCN_BOOL mt6620_quick_sleep_flag_get(VOID);
+
+/*******************************************************************************
+*                            P U B L I C   D A T A
+********************************************************************************
+*/
+
+/* MT6620 Operation Function Table */
+const WMT_IC_OPS wmt_ic_ops_mt6620 = {
+    .icId = 0x6620,
+    .sw_init = mt6620_sw_init,
+    .sw_deinit = mt6620_sw_deinit,
+    .ic_pin_ctrl = mt6620_pin_ctrl,
+    .ic_ver_check = mt6620_ver_check,
+    .co_clock_ctrl = NULL,
+    .is_quick_sleep  = mt6620_quick_sleep_flag_get,
+    .is_aee_dump_support = NULL,
+};
+
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+#if 0
+static INT32
+mt6620_sw_init (
+    P_WMT_HIF_CONF pWmtHifConf
+    )
+{
+    INT32 iRet = -1;
+    UINT32 u4Res = 0;
+    UCHAR evtBuf[256];
+    UINT32 ctrlPa1;
+    UINT32 ctrlPa2;
+    UINT32 hw_ver;
+
+    WMT_DBG_FUNC(" start\n");
+
+    osal_assert(NULL != gp_mt6620_info);
+    if ( (NULL == gp_mt6620_info)
+        || (NULL == pWmtHifConf)
+        ) {
+        WMT_ERR_FUNC("null pointers: gp_mt6620_info(0x%p), pWmtHifConf(0x%p)\n",
+            gp_mt6620_info, pWmtHifConf);
+        return -1;
+    }
+
+    hw_ver = gp_mt6620_info->u4HwVer;
+
+    //4 <3.1> start init for sdio
+    if (WMT_HIF_SDIO == pWmtHifConf->hifType) {
+        /* 1. enable all INT32 */
+        /* 2. disable mcu gate (only MT6620E1/E2) */
+        iRet = wmt_core_init_script(init_table_1_1, osal_array_size(init_table_1_1));
+        if (iRet) {
+            WMT_ERR_FUNC("init_table_1_1 fail:%d\n", iRet);
+            osal_assert(0);
+            return -1;
+        }
+    }
+
+    //4 <3.2> start init for uart
+    if (WMT_HIF_UART == pWmtHifConf->hifType) {
+        /* init variable fields for script execution */
+        osal_memcpy(&WMT_SET_BAUD_CMD_X[5], &pWmtHifConf->au4HifConf[0], osal_sizeof(UINT32));
+        WMT_SET_BAUD_CMD_X[8] = (UCHAR)0x00;//0xC0 MTK Flow Control /* no flow control */
+        osal_memcpy(&WMT_QUERY_BAUD_EVT_X[6], &pWmtHifConf->au4HifConf[0], osal_sizeof(UINT32));
+        WMT_QUERY_BAUD_EVT_X[9] = (UCHAR)0x00; //0xC0 MTK Flow Control /* no flow control */
+
+        /* 3. Query chip baud rate (TEST-ONLY) */
+        /* 4. Query chip STP options (TEST-ONLY) */
+        /* 5. Change chip baud rate: t_baud */
+        //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;
+        }
+
+        /* 6. Set host baudrate and flow control*/
+        ctrlPa1 = pWmtHifConf->au4HifConf[0]; ctrlPa2 = 0;
+        iRet = wmt_core_ctrl(WMT_CTRL_HOST_BAUDRATE_SET, &ctrlPa1, &ctrlPa2);
+        if (iRet) {
+            WMT_ERR_FUNC("change baudrate(%d) fail(%d)\n", pWmtHifConf->au4HifConf[0], iRet);
+            return -3;
+        }
+        WMT_INFO_FUNC("WMT-CORE: change baudrate(%d) ok\n", pWmtHifConf->au4HifConf[0]);
+        
+        /* 7. Wake up chip and check event */
+//          iRet = (*kal_stp_tx_raw)(&WMT_SET_WAKEUP_WAKE_CMD_RAW[0], 1, &u4Res);
+        iRet = wmt_core_tx((PUINT8)&WMT_SET_WAKEUP_WAKE_CMD_RAW[0], 1, &u4Res, MTK_WCN_BOOL_TRUE);
+        if (iRet || (u4Res != 1)) {
+            WMT_ERR_FUNC("write raw iRet(%d) written(%d)\n", iRet, u4Res);
+            return -4;
+        }
+
+        osal_memset(evtBuf, 0, osal_sizeof(evtBuf));
+        iRet = wmt_core_rx(evtBuf, osal_sizeof(WMT_SET_WAKEUP_WAKE_EVT), &u4Res);
+#ifdef CFG_DUMP_EVT
+        WMT_DBG_FUNC("WAKEUP_WAKE_EVT read len %d [%02x,%02x,%02x,%02x,%02x,%02x]\n",
+             (INT32)u4Res, evtBuf[0], evtBuf[1], evtBuf[2], evtBuf[3], evtBuf[4], evtBuf[5]);
+#endif
+        if (iRet || (u4Res != osal_sizeof(WMT_SET_WAKEUP_WAKE_EVT))) {
+            WMT_ERR_FUNC("read WAKEUP_WAKE_EVT fail(%d)\n", iRet);
+            return -5;
+        }
+        //WMT_DBG_FUNC("WMT-CORE: read WMT_SET_WAKEUP_WAKE_EVT ok");
+
+#if CFG_CHECK_WMT_RESULT
+        if (osal_memcmp(evtBuf, WMT_SET_WAKEUP_WAKE_EVT, osal_sizeof(WMT_SET_WAKEUP_WAKE_EVT)) != 0) {
+            WMT_ERR_FUNC("WMT-CORE: write WMT_SET_WAKEUP_WAKE_CMD_RAW status fail\n");
+            return -6;
+        }
+#endif
+
+        /* 8. Query baud rate (TEST-ONLY) */
+        iRet = wmt_core_init_script(init_table_2, osal_array_size(init_table_2));
+        if (iRet) {
+            WMT_ERR_FUNC("init_table_2 fail(%d)\n", iRet);
+            return -7;
+        }
+    }
+
+    /* 9. download patch */
+    iRet = mt6620_patch_dwn();
+    
+    WMT_INFO_FUNC("Not to check the patch validity\n");
+#if 0 
+    if (iRet) {
+        WMT_ERR_FUNC("patch dwn fail (%d)\n", iRet);
+        return -8;
+    }
+    else {
+        WMT_INFO_FUNC("patch dwn ok\n");
+    }
+#endif
+    /* 10. 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 -9;
+    }
+    iRet = wmt_stp_init_coex();
+    if (iRet) {
+        WMT_ERR_FUNC("init_coex fail(%d)\n", iRet);
+        return -10;
+    }
+    else {
+        WMT_INFO_FUNC("init_coex ok\n");
+    }
+
+#if 0
+    /*10-2 enable 32K By Pass Mode*/
+    //if hwVer = E3/E4, please enable 32K by pass mode.
+    //does not support mt6620E1/E2, always enable 32k bypass mode
+    //if ((hwVer == 0x8a10 || hwVer == 0x8a11))
+    {
+        WMT_INFO_FUNC("WMT-CORE: init_table_6 OSC32K");
+        iRet = wmt_core_init_script(init_table_6, osal_array_size(init_table_6));
+        if (iRet == 0) {
+            WMT_DBG_FUNC("WMT-CORE: init_table_6 OSC32K, successful\n");
+        }
+        else {
+            WMT_WARN_FUNC("init table 6 OSC32K fail, continue init...\n");
+            /*return -11;*/
+        }
+    }
+#endif
+
+    if (WMT_HIF_UART == pWmtHifConf->hifType) {
+        /* 11. 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 -12;
+        }
+
+        /* 12. Enable host STP-UART mode */
+        ctrlPa1 = WMT_STP_CONF_MODE; ctrlPa2 = MTKSTP_UART_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-UART-FULL mode fail(%d)\n", iRet);
+            return -13;
+        }
+        WMT_INFO_FUNC("enable host STP-UART-FULL mode\n");
+        /*13. wait for 10ms, enough for chip do mechanism switch.(at least 2ms is needed)*/
+        osal_msleep(10);
+        /* 14. Query chip STP options (TEST-ONLY) */
+        /* 15. Query baud rate (stp, 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 -14;
+        }
+    }
+
+    /* 15. Set FM strap */
+    WMT_STRAP_CONF_CMD_FM_COMM[5] = (UCHAR)pWmtHifConf->au4StrapConf[0];
+    WMT_STRAP_CONF_EVT[5] = (UCHAR)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 -15;
+    }
+    WMT_INFO_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 -16;
+        }
+#endif
+
+#if 0
+    /* 16. trace32 dump when fw assert*/
+    {
+        INT32 val = 0x00000001;
+        WMT_INFO_FUNC("WMT-CORE: enable assert dump");
+        wmt_reg_rw_raw(1, 0x0100092c, &val, 0xFFFFFFFF);
+    }
+#endif
+
+#if CFG_WMT_PS_SUPPORT
+    osal_assert(NULL != gp_mt6620_info);
+    if (NULL != gp_mt6620_info) {
+       if (MTK_WCN_BOOL_FALSE != gp_mt6620_info->bPsmSupport) {
+           wmt_lib_ps_enable();
+       }
+       else {
+           wmt_lib_ps_disable();
+       }
+    }
+#endif
+
+    return 0;
+}
+#endif
+
+static INT32
+mt6620_sw_init (
+    P_WMT_HIF_CONF pWmtHifConf
+    )
+{
+    INT32 iRet = -1;
+    UINT32 u4Res = 0;
+    UCHAR evtBuf[256];
+    UINT32 ctrlPa1;
+    UINT32 ctrlPa2;
+    UINT32 hw_ver;
+       UINT32 patch_num = 0;
+       UINT32 patch_index = 0;
+    WMT_DBG_FUNC(" start\n");
+
+    osal_assert(NULL != gp_mt6620_info);
+    if ( (NULL == gp_mt6620_info)
+        || (NULL == pWmtHifConf)
+        ) {
+        WMT_ERR_FUNC("null pointers: gp_mt6620_info(0x%p), pWmtHifConf(0x%p)\n",
+            gp_mt6620_info, pWmtHifConf);
+        return -1;
+    }
+
+    hw_ver = gp_mt6620_info->u4HwVer;
+
+    //4 <3.1> start init for sdio
+    if (WMT_HIF_SDIO == pWmtHifConf->hifType) {
+        /* 1. enable all INT32 */
+        /* 2. disable mcu gate (only MT6620E1/E2) */
+        iRet = wmt_core_init_script(init_table_1_1, osal_array_size(init_table_1_1));
+        if (iRet) {
+            WMT_ERR_FUNC("init_table_1_1 fail:%d\n", iRet);
+            osal_assert(0);
+            return -1;
+        }
+    }
+
+    //4 <3.2> start init for uart
+    if (WMT_HIF_UART == pWmtHifConf->hifType) {
+
+               /* init variable fields for script execution */
+                osal_memcpy(&WMT_SET_BAUD_CMD_X[5], &pWmtHifConf->au4HifConf[0], osal_sizeof(UINT32));
+                osal_memcpy(&WMT_QUERY_BAUD_EVT_X[6], &pWmtHifConf->au4HifConf[0], osal_sizeof(UINT32));
+                if (WMT_UART_MTK_SW_FC == pWmtHifConf->uartFcCtrl)
+                {
+                        WMT_INFO_FUNC("enable MTK SW Flow Control\n");
+                        WMT_SET_BAUD_CMD_X[8] = (UCHAR)0x80;//* MTK SW flow control */
+                        WMT_QUERY_BAUD_EVT_X[9] = (UCHAR)0x80; //* MTK SW flow control */
+                }
+                else if (WMT_UART_LUX_SW_FC == pWmtHifConf->uartFcCtrl)
+                {
+                        WMT_INFO_FUNC("enable Linux SW Flow Control\n");
+                        WMT_SET_BAUD_CMD_X[8] = (UCHAR)0x80;//* Linux SW flow control */
+                        WMT_QUERY_BAUD_EVT_X[9] = (UCHAR)0x80; //* Linux SW flow control */
+                }
+                else if (WMT_UART_HW_FC == pWmtHifConf->uartFcCtrl)
+                {
+                        WMT_INFO_FUNC("enable HW Flow Control\n");
+                        WMT_SET_BAUD_CMD_X[8] = (UCHAR)0xC0;//* HW flow control */
+                        WMT_QUERY_BAUD_EVT_X[9] = (UCHAR)0xC0; //* HW flow control */
+                }
+                else {
+                        /* WMT_UART_NO_FC and all other cases!!! */
+                        WMT_INFO_FUNC("no Flow Control (uartFcCtrl:%d)\n", pWmtHifConf->uartFcCtrl);
+                        WMT_SET_BAUD_CMD_X[8] = (UCHAR)0x00;//* no flow control */
+                        WMT_QUERY_BAUD_EVT_X[9] = (UCHAR)0x00; //* no flow control */
+                }
+
+        /* 3. Query chip baud rate (TEST-ONLY) */
+        /* 4. Query chip STP options (TEST-ONLY) */
+        /* 5. Change chip baud rate: t_baud */
+        //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;
+        }
+
+        /* 6. Set host baudrate and flow control*/
+        ctrlPa1 = pWmtHifConf->au4HifConf[0]; ctrlPa2 = 0;
+        iRet = wmt_core_ctrl(WMT_CTRL_HOST_BAUDRATE_SET, &ctrlPa1, &ctrlPa2);
+        if (iRet) {
+            WMT_ERR_FUNC("change baudrate(%d) fail(%d)\n", pWmtHifConf->au4HifConf[0], iRet);
+            return -3;
+        }
+        WMT_INFO_FUNC("WMT-CORE: change baudrate(%d) ok\n", pWmtHifConf->au4HifConf[0]);
+        
+        /* 7. Wake up chip and check event */
+//          iRet = (*kal_stp_tx_raw)(&WMT_SET_WAKEUP_WAKE_CMD_RAW[0], 1, &u4Res);
+        iRet = wmt_core_tx((PUINT8)&WMT_SET_WAKEUP_WAKE_CMD_RAW[0], 1, &u4Res, MTK_WCN_BOOL_TRUE);
+        if (iRet || (u4Res != 1)) {
+            WMT_ERR_FUNC("write raw iRet(%d) written(%d)\n", iRet, u4Res);
+            return -4;
+        }
+
+        osal_memset(evtBuf, 0, osal_sizeof(evtBuf));
+        iRet = wmt_core_rx(evtBuf, osal_sizeof(WMT_SET_WAKEUP_WAKE_EVT), &u4Res);
+#ifdef CFG_DUMP_EVT
+        WMT_DBG_FUNC("WAKEUP_WAKE_EVT read len %d [%02x,%02x,%02x,%02x,%02x,%02x]\n",
+             (INT32)u4Res, evtBuf[0], evtBuf[1], evtBuf[2], evtBuf[3], evtBuf[4], evtBuf[5]);
+#endif
+        if (iRet || (u4Res != osal_sizeof(WMT_SET_WAKEUP_WAKE_EVT))) {
+            WMT_ERR_FUNC("read WAKEUP_WAKE_EVT fail(%d)\n", iRet);
+            return -5;
+        }
+        //WMT_DBG_FUNC("WMT-CORE: read WMT_SET_WAKEUP_WAKE_EVT ok");
+
+#if CFG_CHECK_WMT_RESULT
+        if (osal_memcmp(evtBuf, WMT_SET_WAKEUP_WAKE_EVT, osal_sizeof(WMT_SET_WAKEUP_WAKE_EVT)) != 0) {
+            WMT_ERR_FUNC("WMT-CORE: write WMT_SET_WAKEUP_WAKE_CMD_RAW status fail\n");
+            return -6;
+        }
+#endif
+
+        /* 8. Query baud rate (TEST-ONLY) */
+        iRet = wmt_core_init_script(init_table_2, osal_array_size(init_table_2));
+        if (iRet) {
+            WMT_ERR_FUNC("init_table_2 fail(%d)\n", iRet);
+            return -7;
+        }
+    }
+    if (WMT_HIF_UART == pWmtHifConf->hifType) {
+        /* 9. 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 -8;
+        }
+
+        /* 10. Enable host STP-UART mode */
+        ctrlPa1 = WMT_STP_CONF_MODE; ctrlPa2 = MTKSTP_UART_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-UART-FULL mode fail(%d)\n", iRet);
+            return -9;
+        }
+        WMT_INFO_FUNC("enable host STP-UART-FULL mode\n");
+        /*10. wait for 10ms, enough for chip do mechanism switch.(at least 2ms is needed)*/
+        osal_msleep(10);
+        /* 11. Query chip STP options (TEST-ONLY) */
+        /* 12. Query baud rate (stp, 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 -10;
+        }
+    }
+    /* 13. download patch */
+#if CFG_WMT_MULTI_PATCH
+       iRet = mt6620_patch_info_prepare();
+       if(iRet)
+       {
+               WMT_ERR_FUNC("patch info perpare fail(%d)\n",iRet);
+               return -11;
+       }
+       
+       ctrlPa1 = 0;ctrlPa2 = 0;
+       wmt_core_ctrl(WMT_CTRL_GET_PATCH_NUM,&ctrlPa1,&ctrlPa2);
+       patch_num = ctrlPa1;
+       WMT_INFO_FUNC("patch total num = [%d]\n",patch_num);
+
+       for(patch_index = 0;patch_index < patch_num;patch_index++)
+       {
+               iRet = mt6620_patch_dwn(patch_index);
+               if(iRet){
+                       WMT_ERR_FUNC("patch dwn fail (%d),patch_index(%d)\n", iRet,patch_index);
+               return -12;
+               }
+               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 -13;
+           }
+       }
+#else
+    iRet = mt6620_patch_dwn();
+    
+    WMT_INFO_FUNC("Not to check the patch validity\n");
+#if 0 
+    if (iRet) {
+        WMT_ERR_FUNC("patch dwn fail (%d)\n", iRet);
+        return -11;
+    }
+    else {
+        WMT_INFO_FUNC("patch dwn ok\n");
+    }
+#endif
+    /* 14. 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 -13;
+    }
+#endif
+    iRet = wmt_stp_init_coex();
+    if (iRet) {
+        WMT_ERR_FUNC("init_coex fail(%d)\n", iRet);
+        return -14;
+    }
+    else {
+        WMT_INFO_FUNC("init_coex ok\n");
+    }
+
+#if 0
+    /*10-2 enable 32K By Pass Mode*/
+    //if hwVer = E3/E4, please enable 32K by pass mode.
+    //does not support mt6620E1/E2, always enable 32k bypass mode
+    //if ((hwVer == 0x8a10 || hwVer == 0x8a11))
+    {
+        WMT_INFO_FUNC("WMT-CORE: init_table_6 OSC32K");
+        iRet = wmt_core_init_script(init_table_6, osal_array_size(init_table_6));
+        if (iRet == 0) {
+            WMT_DBG_FUNC("WMT-CORE: init_table_6 OSC32K, successful\n");
+        }
+        else {
+            WMT_WARN_FUNC("init table 6 OSC32K fail, continue init...\n");
+            /*return -14;*/
+        }
+    }
+#endif
+
+
+
+    /* 15. Set FM strap */
+    WMT_STRAP_CONF_CMD_FM_COMM[5] = (UCHAR)pWmtHifConf->au4StrapConf[0];
+    WMT_STRAP_CONF_EVT[5] = (UCHAR)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 -15;
+    }
+    WMT_INFO_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 -16;
+        }
+#endif
+
+#if 0
+    /* 16. trace32 dump when fw assert*/
+    {
+        INT32 val = 0x00000001;
+        WMT_INFO_FUNC("WMT-CORE: enable assert dump");
+        wmt_reg_rw_raw(1, 0x0100092c, &val, 0xFFFFFFFF);
+    }
+#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 -17;
+        } else {
+            WMT_INFO_FUNC("enable mt662x firmware coredump\n");
+        }
+    }
+    else
+    {
+        WMT_INFO_FUNC("disable mt662x firmware coredump\n");
+    }
+
+#if CFG_WMT_PS_SUPPORT
+    osal_assert(NULL != gp_mt6620_info);
+    if (NULL != gp_mt6620_info) {
+       if (MTK_WCN_BOOL_FALSE != gp_mt6620_info->bPsmSupport) {
+           wmt_lib_ps_enable();
+       }
+       else {
+           wmt_lib_ps_disable();
+       }
+    }
+#endif
+
+    return 0;
+}
+
+
+static INT32
+mt6620_sw_deinit (
+    P_WMT_HIF_CONF pWmtHifConf
+    )
+{
+    WMT_DBG_FUNC(" start\n");
+
+#if CFG_WMT_PS_SUPPORT
+    osal_assert(NULL != gp_mt6620_info);
+    if ( (NULL != gp_mt6620_info)
+        && (MTK_WCN_BOOL_FALSE != gp_mt6620_info->bPsmSupport) ) {
+           wmt_lib_ps_disable();
+       }
+#endif
+
+    gp_mt6620_info = NULL;
+
+    return 0;
+}
+
+static INT32
+mt6620_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");
+        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 {
+         /*PCM & I2S separate*/
+        WMT_INFO_FUNC("PCM & I2S PIN SEPARATE\n");
+        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);
+
+        default:
+            WMT_ERR_FUNC("unsupported state (%d) \n", state);
+            ret = -1;
+            break;
+        }
+    }
+
+    if (!ret) {
+        WMT_INFO_FUNC("new state(%d) ok\n", state);
+    }
+    else {
+        WMT_WARN_FUNC("new state(%d) fail(%d)\n", state, ret);
+    }
+
+    return ret;
+}
+
+static INT32
+mt6620_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 = mt6620_aif_ctrl(state, flag);
+        break;
+
+    case WMT_IC_PIN_EEDI:
+        WMT_WARN_FUNC("TBD!!");
+        ret = -1;
+        break;
+
+    case WMT_IC_PIN_EEDO:
+        WMT_WARN_FUNC("TBD!!");
+        ret = -1;
+        break;
+    case WMT_IC_PIN_GSYNC:
+        ret = -1;
+        WMT_WARN_FUNC("TBD!!");
+        break;
+    default:
+        break;
+    }
+    WMT_INFO_FUNC("ret = (%d)\n" , ret);
+
+    return ret;
+}
+
+
+static MTK_WCN_BOOL mt6620_quick_sleep_flag_get(VOID)
+{
+    return MTK_WCN_BOOL_FALSE;
+}
+
+
+
+static INT32
+mt6620_ver_check (VOID)
+{
+    UINT32 hw_ver;
+    UINT32 fw_ver;
+    INT32 iret;
+    const WMT_IC_INFO_S *p_info;
+    UINT32 ctrlPa1;
+    UINT32 ctrlPa2;
+
+    /* 1. identify chip versions: HVR(HW_VER) and FVR(FW_VER) */
+    WMT_LOUD_FUNC("MT6620: before read hw_ver (hw version)\n");
+    iret = wmt_core_reg_rw_raw(0, GEN_HVR, &hw_ver, GEN_VER_MASK);
+    if (iret) {
+        WMT_ERR_FUNC("MT6620: read hw_ver fail:%d\n", iret);
+        return -2;
+    }
+    WMT_INFO_FUNC("MT6620: read hw_ver (hw version) (0x%x)\n", hw_ver);
+
+    WMT_LOUD_FUNC("MT6620: before fw_ver (rom version) \n");
+    wmt_core_reg_rw_raw(0, GEN_FVR, &fw_ver, GEN_VER_MASK);
+    if (iret) {
+        WMT_ERR_FUNC("MT6620: read fw_ver fail:%d\n", iret);
+        return -2;
+    }
+    WMT_INFO_FUNC("MT6620: read fw_ver (rom version) (0x%x)\n", fw_ver);
+
+    p_info = mt6620_find_wmt_ic_info(hw_ver);
+    if (NULL == p_info) {
+        WMT_ERR_FUNC("MT6620: hw_ver(0x%x) find wmt ic info fail\n");
+        return -3;
+    }
+
+    WMT_INFO_FUNC("MT6620: wmt ic info: %s.%s (0x%x, WMTHWVER:%d, patch_ext:%s)\n",
+        p_info->cChipName, p_info->cChipVersion,
+        p_info->u4HwVer, p_info->eWmtHwVer,
+        p_info->cPatchNameExt);
+
+    /* hw id & version */
+    ctrlPa1 = (0x00006620UL << 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("MT6620: WMT_CTRL_HWIDVER_SET fail(%d)\n", iret);
+    }
+
+    gp_mt6620_info = p_info;
+    return 0;
+}
+
+static const WMT_IC_INFO_S*
+mt6620_find_wmt_ic_info (
+    const UINT32 hw_ver
+    )
+{
+    /* match chipversion with u4HwVer item in mt6620_info_table */
+    const UINT32 size = osal_array_size(mt6620_info_table);
+    INT32 index;
+
+    /* 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 != mt6620_info_table[index].u4HwVer) /* full match */
+        ) {
+        --index;
+    }
+    if (0 <= index) {
+        WMT_INFO_FUNC("found ic info(0x%x) by full match! index:%d\n", hw_ver, index);
+        return &mt6620_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(mt6620_info_table[index].u4HwVer))
+        ) {
+        --index;
+    }
+    if (0 <= index) {
+        WMT_INFO_FUNC("MT6620: found ic info for hw_ver(0x%x) by major num! index:%d\n", hw_ver, index);
+        return &mt6620_info_table[index];
+    }
+
+    WMT_ERR_FUNC("MT6620: find no ic info for hw_ver(0x%x) by full match nor major num match!\n", hw_ver);
+    return NULL;
+}
+
+
+static INT32
+wmt_stp_init_coex (VOID)
+{
+    INT32 iRet;
+    UINT32 addr;
+    WMT_GEN_CONF *pWmtGenConf;
+
+    #define COEX_WMT  0
+    #define COEX_BT   1
+    #define COEX_WIFI 2
+    #define COEX_PTA  3
+    #define COEX_MISC 4
+
+    /*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 0x%x 0x%x\n",
+        pWmtGenConf->coex_wmt_ant_mode,
+        pWmtGenConf->coex_wmt_wifi_time_ctl,
+        pWmtGenConf->coex_wmt_ext_pta_dev_on
+        );
+    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
+        );
+
+    /*command adjustion due to WMT.cfg*/
+    coex_table[COEX_WMT].cmd[5]= pWmtGenConf->coex_wmt_ant_mode;
+    coex_table[COEX_WMT].cmd[6]= pWmtGenConf->coex_wmt_wifi_time_ctl;
+    coex_table[COEX_WMT].cmd[7]= pWmtGenConf->coex_wmt_ext_pta_dev_on;
+    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);
+    }
+
+    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));
+    if (gWmtDbgLvl >= WMT_LOG_DBG) {
+        wmt_core_dump_data(& coex_table[COEX_MISC].cmd[0], coex_table[COEX_MISC].str, coex_table[COEX_MISC].cmdSz);
+    }
+    iRet = wmt_core_init_script(coex_table, sizeof(coex_table)/sizeof(coex_table[0]));
+
+    return iRet;
+}
+
+#if CFG_WMT_MULTI_PATCH
+
+static INT32 mt6620_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
+mt6620_patch_dwn (UINT32 index)
+{
+    INT32 iRet = -1;
+    P_WMT_PATCH patchHdr = NULL;
+    PUINT8 pbuf = NULL;
+    UINT32 patchSize = 0;
+    UINT32 fragSeq = 0;
+    UINT32 fragNum = 0;
+    UINT16 fragSize = 0;
+    UINT16 cmdLen;
+    UINT32 offset;
+    UINT32 u4Res;
+    UINT8 patchevtBuf[8];
+       UINT8 addressevtBuf[12];
+       UCHAR addressByte[4];
+    PCHAR cDataTime = NULL;
+    /*PCHAR 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_mt6620_info) {
+        WMT_ERR_FUNC("null gp_mt6620_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] = (UINT32)&gFullPatchName;
+       ctrlData.au4CtrlData[2] = (UINT32)&addressByte;
+       iRet = wmt_ctrl(&ctrlData);
+       WMT_INFO_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] = (UINT32)NULL;
+       ctrlData.au4CtrlData[1] = (UINT32)&gFullPatchName;
+                       
+       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';
+
+    /* remove patch header:
+    * |<-patch body: X Bytes (X=patchSize)--->|
+    */
+    patchSize -= sizeof(WMT_PATCH);
+    pbuf += sizeof(WMT_PATCH);
+
+       if(index == 0)
+       {
+           WMT_INFO_FUNC("===========================================\n");
+           WMT_INFO_FUNC("[Combo Patch] Built Time = %s\n", cDataTime);
+           WMT_INFO_FUNC("[Combo Patch] Hw Ver = 0x%x\n", ((u2HwVer & 0x00ff) << 8) | ((u2HwVer & 0xff00) >> 8));
+           WMT_INFO_FUNC("[Combo Patch] Sw Ver = 0x%x\n", ((u2SwVer & 0x00ff) << 8) | ((u2SwVer & 0xff00) >> 8));
+           WMT_INFO_FUNC("[Combo Patch] Ph Ver = 0x%04x\n",  ((u4PatchVer & 0xff000000) >> 24) | ((u4PatchVer & 0x00ff0000) >> 16));
+           WMT_INFO_FUNC("[Combo Patch] Platform = %c%c%c%c\n", patchHdr->ucPLat[0],
+               patchHdr->ucPLat[1], patchHdr->ucPLat[2], patchHdr->ucPLat[3]);
+           WMT_INFO_FUNC("[Combo Patch] Content Size = 0x%x\n", patchSize);
+           WMT_INFO_FUNC("[Combo Patch] Content CRC = 0x%04x\n", osal_crc16(pbuf, patchSize));
+           WMT_INFO_FUNC("===========================================\n");
+       }
+
+    patchSizePerFrag = (MAJORNUM(gp_mt6620_info->u4HwVer) != 0) ?
+        DEFAULT_PATCH_FRAG_SIZE : MT6620E2_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 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_INFO_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 = -4;
+            break;
+        }
+        WMT_DBG_FUNC("wmt_core: write fragSeq(%d) size(%d, %d) ok\n",
+            fragSeq, fragSize + sizeof(WMT_PATCH_CMD), u4Res);
+
+        osal_memset(patchevtBuf, 0, sizeof(patchevtBuf));
+        //iRet = (*kal_stp_rx)(evtBuf, sizeof(WMT_PATCH_EVT), &u4Res);
+        iRet = wmt_core_rx(patchevtBuf, 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 = -5;
+            break;
+        }
+#if CFG_CHECK_WMT_RESULT
+        if (osal_memcmp(patchevtBuf, WMT_PATCH_EVT, sizeof(WMT_PATCH_EVT)) != 0) {
+            WMT_ERR_FUNC("wmt_core: compare WMT_PATCH_EVT result error rx(%d):[%02X,%02X,%02X,%02X,%02X] exp(%d):[%02X,%02X,%02X,%02X,%02X]\n",
+                u4Res, patchevtBuf[0], patchevtBuf[1], patchevtBuf[2], patchevtBuf[3], patchevtBuf[4], 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 = -6;
+            break;
+        }
+#endif
+        WMT_DBG_FUNC("wmt_core: read WMT_PATCH_EVT length(%d, %d) ok\n",
+            sizeof(WMT_PATCH_EVT), u4Res);
+
+#if 0
+        WMT_DBG_FUNC("wmt_core: send patch frag(%d) [%02X,%02X,%02X,%02X,%02X] (%d) ok",
+            fragSeq, WMT_PATCH_CMD[0], WMT_PATCH_CMD[1], WMT_PATCH_CMD[2],
+            WMT_PATCH_CMD[3], WMT_PATCH_CMD[4], fragSize);
+#endif
+
+        offset += patchSizePerFrag;
+        ++fragSeq;
+    }
+
+    WMT_INFO_FUNC("wmt_core: patch dwn:%d frag(%d, %d) %s\n",
+        iRet, fragSeq, fragSize, (!iRet && (fragSeq == fragNum)) ? "ok": "fail");
+
+    if (fragSeq != fragNum) {
+        iRet = -7;
+    }
+done:
+    /* WMT_CTRL_FREE_PATCH always return 0 */
+       ctrlData.ctrlId = WMT_CTRL_FREE_PATCH;
+       ctrlData.au4CtrlData[0] = index + 1;
+       wmt_ctrl(&ctrlData);
+    //wmt_core_ctrl(WMT_CTRL_FREE_PATCH, NULL, NULL);
+    if ( (iRet == -2) || (iRet == -3) ) {
+        /*no patch found or patch version does not match with hw version, we check if patch is mandatory or not, if yes, return iRet, if not return 0*/
+        if (MTK_WCN_BOOL_FALSE != gp_mt6620_info->bWorkWithoutPatch) {
+            iRet = 0;
+        }
+    }
+
+    return iRet;
+}
+
+
+#else
+static INT32
+mt6620_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];
+    PCHAR cDataTime = NULL;
+    /*PCHAR 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_mt6620_info) {
+        WMT_ERR_FUNC("null gp_mt6620_info!\n");
+        return -1;
+    }
+#if 0
+               ctrlData.ctrlId = WMT_CTRL_GET_PATCH_NAME;
+               ctrlData.au4CtrlData[0] = (UINT32)&gDefPatchName;
+               iRet = wmt_ctrl(&ctrlData);
+       
+               if (mt6620_update_patch_name()) {
+                       WMT_ERR_FUNC("invalid patch name, ommit patch download process.\n");
+                       return -1;
+               }
+       
+               ctrlData.ctrlId = WMT_CTRL_GET_PATCH;
+               ctrlData.au4CtrlData[0] = (UINT32)&gDefPatchName;
+               ctrlData.au4CtrlData[1] = (UINT32)&gFullPatchName;
+               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 = -2;
+                       goto done;
+               }
+#else
+               //<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;
+               }
+       
+#endif
+
+    /* |<-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';
+
+    /* remove patch header:
+    * |<-patch body: X Bytes (X=patchSize)--->|
+    */
+    patchSize -= sizeof(WMT_PATCH);
+    pbuf += sizeof(WMT_PATCH);
+    WMT_INFO_FUNC("===========================================\n");
+    WMT_INFO_FUNC("[Combo Patch] Built Time = %s\n", cDataTime);
+    WMT_INFO_FUNC("[Combo Patch] Hw Ver = 0x%x\n", ((u2HwVer & 0x00ff) << 8) | ((u2HwVer & 0xff00) >> 8));
+    WMT_INFO_FUNC("[Combo Patch] Sw Ver = 0x%x\n", ((u2SwVer & 0x00ff) << 8) | ((u2SwVer & 0xff00) >> 8));
+    WMT_INFO_FUNC("[Combo Patch] Ph Ver = 0x%04x\n",  ((u4PatchVer & 0xff000000) >> 24) | ((u4PatchVer & 0x00ff0000) >> 16));
+    WMT_INFO_FUNC("[Combo Patch] Platform = %c%c%c%c\n", patchHdr->ucPLat[0],
+        patchHdr->ucPLat[1], patchHdr->ucPLat[2], patchHdr->ucPLat[3]);
+    WMT_INFO_FUNC("[Combo Patch] Content Size = 0x%x\n", patchSize);
+    WMT_INFO_FUNC("[Combo Patch] Content CRC = 0x%04x\n", osal_crc16(pbuf, patchSize));
+    WMT_INFO_FUNC("===========================================\n");
+
+    patchSizePerFrag = (MAJORNUM(gp_mt6620_info->u4HwVer) != 0) ?
+        DEFAULT_PATCH_FRAG_SIZE : MT6620E2_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 = -4;
+            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 = -5;
+            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 result error 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], 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 = -6;
+            break;
+        }
+#endif
+        WMT_DBG_FUNC("wmt_core: read WMT_PATCH_EVT length(%d, %d) ok\n",
+            sizeof(WMT_PATCH_EVT), u4Res);
+
+#if 0
+        WMT_DBG_FUNC("wmt_core: send patch frag(%d) [%02X,%02X,%02X,%02X,%02X] (%d) ok",
+            fragSeq, WMT_PATCH_CMD[0], WMT_PATCH_CMD[1], WMT_PATCH_CMD[2],
+            WMT_PATCH_CMD[3], WMT_PATCH_CMD[4], fragSize);
+#endif
+
+        offset += patchSizePerFrag;
+        ++fragSeq;
+    }
+
+    WMT_INFO_FUNC("wmt_core: patch dwn:%d frag(%d, %d) %s\n",
+        iRet, fragSeq, fragSize, (!iRet && (fragSeq == fragNum)) ? "ok": "fail");
+
+    if (fragSeq != fragNum) {
+        iRet = -7;
+    }
+done:
+    /* WMT_CTRL_FREE_PATCH always return 0 */
+    wmt_core_ctrl(WMT_CTRL_FREE_PATCH, NULL, NULL);
+    if ( (iRet == -2) || (iRet == -3) ) {
+        /*no patch found or patch version does not match with hw version, we check if patch is mandatory or not, if yes, return iRet, if not return 0*/
+        if (MTK_WCN_BOOL_FALSE != gp_mt6620_info->bWorkWithoutPatch) {
+            iRet = 0;
+        }
+    }
+
+    return iRet;
+}
+
+static INT32
+mt6620_update_patch_name (VOID)
+{
+    INT32 len;
+    UCHAR cTmpPatchName[NAME_MAX + 1] = {0};
+
+    /*init.get hardware version */
+    // TODO:[FixMe][GeorgeKuo]: check using memcpy or strncpy???
+    /*osal_memcpy (gFullPatchName, gDefPatchName, osal_strlen(gDefPatchName));*/
+    osal_strncpy(gFullPatchName, gDefPatchName, osal_sizeof(gFullPatchName));
+
+    /*1.check hardware information */
+    if (NULL == gp_mt6620_info) {
+        WMT_ERR_FUNC("null gp_mt6620_info!\n");
+        osal_memset(gFullPatchName, 0, osal_sizeof(gFullPatchName));
+        return -1;
+    }
+
+    /*2.make possible firmware patch name with original name and hardware version*/
+    if ( (osal_strlen(gDefPatchName) > osal_strlen(WMT_IC_PATCH_TAIL))
+        && ((osal_strlen(gDefPatchName) + osal_strlen(WMT_IC_PATCH_DUMMY_EXT) <= NAME_MAX))
+        ) {
+        len = osal_strlen(gDefPatchName) - osal_strlen(WMT_IC_PATCH_TAIL);
+        osal_memcpy (cTmpPatchName, gDefPatchName, len > NAME_MAX ? NAME_MAX : len);
+        osal_memcpy (cTmpPatchName + osal_strlen(cTmpPatchName), gp_mt6620_info->cPatchNameExt, osal_strlen(gp_mt6620_info->cPatchNameExt));
+        osal_memcpy (cTmpPatchName + osal_strlen(cTmpPatchName), WMT_IC_PATCH_TAIL, osal_strlen(WMT_IC_PATCH_TAIL));
+        cTmpPatchName[osal_strlen(cTmpPatchName)] = '\0';
+    }
+    else {
+        WMT_ERR_FUNC("invalid default firmware patch name (%s)\n", gDefPatchName);
+        osal_memset(gFullPatchName, 0, osal_sizeof(gFullPatchName));
+        return -2;
+    }
+
+    /*patch with versioned name exist , update cFullPatchName with full named patch*/
+    osal_memcpy (gFullPatchName, cTmpPatchName, osal_strlen(cTmpPatchName));
+    *(gFullPatchName + osal_strlen(cTmpPatchName)) = '\0';
+    WMT_INFO_FUNC("full firmware patch name: %s\n", cTmpPatchName);
+
+    return 0;
+}
+#endif
+
diff --git a/drivers/mtk_wcn_combo/common/core/wmt_ic_6628.c b/drivers/mtk_wcn_combo/common/core/wmt_ic_6628.c
new file mode 100755 (executable)
index 0000000..0b966fe
--- /dev/null
@@ -0,0 +1,1959 @@
+/*! \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_MT6628 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)
+#define CFG_WMT_BT_PORT2 (0) /* BT Port 2 Feature. this command does not need after coex command is downconfirmed by LC,*/
+
+#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)
+
+/*******************************************************************************
+*                             D A T A   T Y P E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                           P R I V A T E   D A T A
+********************************************************************************
+*/
+
+static UCHAR gFullPatchName[NAME_MAX + 1];
+static const WMT_IC_INFO_S *gp_mt6628_info = NULL;
+static WMT_CO_CLOCK gCoClockEn = WMT_CO_CLOCK_DIS;
+#if 0
+static UCHAR WMT_WAKEUP_DIS_GATE_CMD[] = {0x1, 0x3, 0x01, 0x00, 0x04};
+static UCHAR WMT_WAKEUP_DIS_GATE_EVT[] = {0x2, 0x3, 0x02, 0x0, 0x0, 0x04};
+
+static UCHAR WMT_WAKEUP_EN_GATE_CMD[] = {0x1, 0x3, 0x01, 0x00, 0x05};
+static UCHAR WMT_WAKEUP_EN_GATE_EVT[] = {0x2, 0x3, 0x02, 0x0, 0x0, 0x05};
+#endif
+
+static UCHAR WMT_QUERY_BAUD_CMD[] = {0x01, 0x04, 0x01, 0x00, 0x02};
+static UCHAR WMT_QUERY_BAUD_EVT_115200[] = {0x02, 0x04, 0x06, 0x00, 0x00, 0x02, 0x00, 0xC2, 0x01, 0x00};
+static UCHAR WMT_QUERY_BAUD_EVT_X[] = {0x02, 0x04, 0x06, 0x00, 0x00, 0x02, 0xAA, 0xAA, 0xAA, 0xBB};
+static UCHAR WMT_QUERY_STP_CMD[] = {0x01, 0x04, 0x01, 0x00, 0x04};
+static UCHAR WMT_QUERY_STP_EVT_DEFAULT[] = {0x02, 0x04, 0x06, 0x00, 0x00, 0x04, 0x11, 0x00, 0x00, 0x00};
+static UCHAR WMT_QUERY_STP_EVT_UART[] = {0x02, 0x04, 0x06, 0x00, 0x00, 0x04, 0xDF, 0x0E, 0x68, 0x01};
+static UCHAR WMT_SET_BAUD_CMD_X[] = {0x01, 0x04, 0x05, 0x00, 0x01, 0xAA, 0xAA, 0xAA, 0xBB};
+static UCHAR WMT_SET_BAUD_EVT[] = {0x02, 0x04, 0x02, 0x00, 0x00, 0x01};
+static UCHAR WMT_SET_WAKEUP_WAKE_CMD_RAW[] = {0xFF};
+static UCHAR WMT_SET_WAKEUP_WAKE_EVT[] = {0x02, 0x03, 0x02, 0x00, 0x00, 0x03};
+static UCHAR WMT_PATCH_CMD[] = {0x01, 0x01, 0x00, 0x00, 0x00};
+static UCHAR WMT_PATCH_EVT[] = {0x02, 0x01, 0x01, 0x00, 0x00};
+static UCHAR WMT_RESET_CMD[] = {0x01, 0x07, 0x01, 0x00, 0x04};
+static UCHAR WMT_RESET_EVT[] = {0x02, 0x07, 0x01, 0x00, 0x00};
+#if CFG_WMT_BT_PORT2
+static UCHAR WMT_BTP2_CMD[] = {0x01, 0x10, 0x03, 0x00, 0x01, 0x03, 0x01};
+static UCHAR WMT_BTP2_EVT[] = {0x02, 0x10, 0x01, 0x00, 0x00};
+#endif
+
+#if CFG_WMT_MULTI_PATCH
+static UCHAR WMT_PATCH_ADDRESS_CMD[] = {0x01,0x08,0x10,0x00,0x01,0x01,0x00,0x01,0xD4,0x01,0x09,0xF0,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff};
+static UCHAR WMT_PATCH_ADDRESS_EVT[] = {0x02,0x08,0x04,0x00,0x00,0x00,0x00,0x01};
+static UCHAR WMT_PATCH_P_ADDRESS_CMD[] = {0x01,0x08,0x10,0x00,0x01,0x01,0x00,0x01,0x48,0x03,0x09,0xF0,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff};
+static UCHAR WMT_PATCH_P_ADDRESS_EVT[] = {0x02,0x08,0x04,0x00,0x00,0x00,0x00,0x01};
+#endif
+
+/*coex cmd/evt++*/
+static UCHAR WMT_COEX_SETTING_CONFIG_CMD[] = {0x01, 0x10, 0x02, 0x00, 0x01, 0x00};
+static UCHAR WMT_COEX_SETTING_CONFIG_EVT[] = {0x02, 0x10, 0x01, 0x00, 0x00};
+
+#if CFG_SUBSYS_COEX_NEED
+static UCHAR WMT_BT_COEX_SETTING_CONFIG_CMD[] = {0x01, 0x10, 0x0B,
+                                                         0x00, 0x02,
+                                                         0x00, 0x00, 0x00, 0x00,
+                                                         0xBB,0xCC,0xDD,0xEE,0xFF,0xAA};
+static UCHAR WMT_BT_COEX_SETTING_CONFIG_EVT[] = {0x02, 0x10, 0x01, 0x00, 0x00};
+static UCHAR WMT_WIFI_COEX_SETTING_CONFIG_CMD[] = {0x01, 0x10, 0x0C,
+                                                           0x00, 0x03,
+                                                           0x00, 0x00,0x00,0x00,0x00,
+                                                           0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0xAA};
+static UCHAR WMT_WIFI_COEX_SETTING_CONFIG_EVT[] = {0x02, 0x10, 0x01, 0x00, 0x00};
+static UCHAR WMT_PTA_COEX_SETTING_CONFIG_CMD[] = {0x01, 0x10, 0x0A,
+                                                          0x00, 0x04,
+                                                          0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xEE, 0xFF, 0xFF, 0xFE};
+static UCHAR WMT_PTA_COEX_SETTING_CONFIG_EVT[] = {0x02, 0x10, 0x01, 0x00, 0x00};
+static UCHAR WMT_MISC_COEX_SETTING_CONFIG_CMD[] = {0x01, 0x10, 0x09,
+                                                           0x00, 0x05,
+                                                           0xAA, 0xAA, 0xAA, 0xAA,
+                                                           0xBB, 0xBB, 0xBB, 0xBB};
+static UCHAR WMT_MISC_COEX_SETTING_CONFIG_EVT[] = {0x02, 0x10, 0x01, 0x00, 0x00};
+#endif
+
+/*coex cmd/evt--*/
+static UCHAR WMT_SET_STP_CMD[] = {0x01, 0x04, 0x05, 0x00, 0x03, 0xDF, 0x0E, 0x68, 0x01};
+static UCHAR WMT_SET_STP_EVT[] = {0x02, 0x04, 0x02, 0x00, 0x00, 0x03};
+static UCHAR WMT_STRAP_CONF_CMD_FM_COMM[] = {0x01, 0x05, 0x02, 0x00, 0x02, 0x02};
+static UCHAR WMT_STRAP_CONF_EVT[] = {0x02, 0x05, 0x02, 0x00, 0x00, 0x02};
+#if 0
+static UCHAR WMT_SET_OSC32K_BYPASS_CMD[]= {0x01, 0x0A, 0x01, 0x00, 0x05};
+static UCHAR 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 UCHAR  WMT_CORE_DUMP_LEVEL_01_CMD[] = {0x1, 0x0F, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static UCHAR  WMT_CORE_DUMP_LEVEL_01_EVT[] = {0x2, 0x0F, 0x01, 0x00, 0x00};
+//to get task and system stack dump when f/w assert
+static UCHAR  WMT_CORE_DUMP_LEVEL_02_CMD[] = {0x1, 0x0F, 0x07, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static UCHAR  WMT_CORE_DUMP_LEVEL_02_EVT[] = {0x2, 0x0F, 0x01, 0x00, 0x00};
+//to get bt related memory dump when f/w assert
+static UCHAR  WMT_CORE_DUMP_LEVEL_03_CMD[] = {0x1, 0x0F, 0x07, 0x00, 0x03, 0x00, 0x00, 0x09, 0xF0, 0x00, 0x0A};
+static UCHAR  WMT_CORE_DUMP_LEVEL_03_EVT[] = {0x2, 0x0F, 0x01, 0x00, 0x00};
+#endif
+//to get full dump when f/w assert
+static UCHAR  WMT_CORE_DUMP_LEVEL_04_CMD[] = {0x1, 0x0F, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static UCHAR  WMT_CORE_DUMP_LEVEL_04_EVT[] = {0x2, 0x0F, 0x01, 0x00, 0x00};
+
+static UCHAR  WMT_CORE_CO_CLOCK_CMD[] = {0x1, 0x0A, 0x02, 0x00, 0x08, 0x03};
+static UCHAR  WMT_CORE_CO_CLOCK_EVT[] = {0x2, 0x0A, 0x01, 0x00, 0x00};
+
+
+#if (MTK_WCN_CMB_MERGE_INTERFACE_SUPPORT)
+static UCHAR 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 UCHAR WMT_SET_I2S_SLAVE_REG_EVT[] = {0x02, 0x08, 0x04, 0x00/*length*/
+    ,0x00 /*S: 0*/
+    ,0x00 /*type: reg */
+    ,0x00 /*rev*/
+    ,0x01 /*1 registers*/
+};
+
+static UCHAR 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 UCHAR WMT_SET_DAI_TO_PAD_REG_EVT[] = {0x02, 0x08, 0x04, 0x00/*length*/
+    ,0x00 /*S: 0*/
+    ,0x00 /*type: reg */
+    ,0x00 /*rev*/
+    ,0x01 /*1 registers*/
+};
+static UCHAR 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 UCHAR WMT_SET_DAI_REG_EVT[] = {0x02, 0x08, 0x04, 0x00/*length*/
+    ,0x00 /*S: 0*/
+    ,0x00 /*type: reg */
+    ,0x00 /*rev*/
+    ,0x01 /*1 registers*/
+};
+#endif
+
+
+#ifndef CFG_IC_MT6628 //For MT6628 no need to set ALLEINT registers, done in f/w
+/* enable all interrupt */
+static UCHAR 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 UCHAR 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 UCHAR 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 UCHAR 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 UCHAR 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 UCHAR 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 UCHAR 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 UCHAR 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 UCHAR 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 UCHAR 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 UCHAR 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 UCHAR WMT_SET_MCUIRQ_REG_EVT[] = {0x02, 0x08, 0x04, 0x00/*length*/
+    ,0x00 /* S: 0 */
+    ,0x00 /* type: reg */
+    ,0x00 /* rev */
+    ,0x05 /* 5 registers */
+};
+#endif
+#endif
+
+static UCHAR WMT_SET_CRYSTAL_TRIMING_CMD[] = {0x01, 0x12, 0x02, 0x00, 0x01, 0x00};
+static UCHAR WMT_SET_CRYSTAL_TRIMING_EVT[] = {0x02, 0x12, 0x02, 0x00, 0x01, 0x00};
+
+static UCHAR WMT_GET_CRYSTAL_TRIMING_CMD[] = {0x01, 0x12, 0x02, 0x00, 0x00, 0x00};
+static UCHAR WMT_GET_CRYSTAL_TRIMING_EVT[] = {0x02, 0x12, 0x02, 0x00, 0x00, 0x00};
+
+/* set sdio driving */
+static UCHAR 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 UCHAR WMT_SET_SDIO_DRV_REG_EVT[] = {0x02, 0x08, 0x04, 0x00/*length*/
+    ,0x00 /*S: 0*/
+    ,0x00 /*type: reg */
+    ,0x00 /*rev*/
+    ,0x01 /*1 registers*/
+};
+
+
+#ifndef CFG_IC_MT6628
+
+/* 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_BAUD_CMD, WMT_QUERY_BAUD_EVT_115200, "query baud 115200"),
+    INIT_CMD(WMT_QUERY_STP_CMD, WMT_QUERY_STP_EVT_DEFAULT, "query stp default"),
+    INIT_CMD(WMT_SET_BAUD_CMD_X, WMT_SET_BAUD_EVT, "set baud rate"),
+};
+
+
+static struct init_script init_table_2[] =
+{
+    INIT_CMD(WMT_QUERY_BAUD_CMD, WMT_QUERY_BAUD_EVT_X, "query baud X"),
+};
+
+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
+};
+
+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"),
+};
+
+
+#if 0
+static struct init_script init_table_3_1[] =
+{
+    INIT_CMD(WMT_WAKEUP_EN_GATE_CMD, WMT_WAKEUP_EN_GATE_EVT, "ensable gating"),
+};
+#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_UART, "query stp uart"),
+    INIT_CMD(WMT_QUERY_BAUD_CMD, WMT_QUERY_BAUD_EVT_X, "query baud X"),
+};
+
+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[] = {
+#if 0
+    INIT_CMD(WMT_CORE_DUMP_EN_CMD, WMT_CORE_DUMP_EN_EVT, "configure memory and core dump"),
+#endif
+    INIT_CMD(WMT_CORE_DUMP_LEVEL_04_CMD, WMT_CORE_DUMP_LEVEL_04_EVT , "setup core dump level"),
+};
+
+#if 0
+static struct init_script init_table_6[] =
+{
+    INIT_CMD(WMT_SET_OSC32K_BYPASS_CMD, WMT_SET_OSC32K_BYPASS_EVT, "set OSC32k by pass mode."),
+};
+#endif
+
+#if defined(CFG_SET_OPT_REG) && 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
+
+
+static struct init_script sdio_driving_table[] = {
+     INIT_CMD(WMT_SET_SDIO_DRV_REG_CMD, WMT_SET_SDIO_DRV_REG_EVT, "sdio_driving"),
+};
+
+
+/* MT6628 Chip Version and Info Table */
+static const WMT_IC_INFO_S mt6628_info_table[] = {
+    {
+        .u4HwVer            = 0x8A00,
+        .cChipName         = WMT_IC_NAME_MT6628,
+        .cChipVersion      = WMT_IC_VER_E1,
+        .cPatchNameExt     = WMT_IC_PATCH_E1_EXT,
+        //need to refine?
+        .eWmtHwVer        = WMTHWVER_MT6620_E1,
+        .bWorkWithoutPatch = MTK_WCN_BOOL_FALSE,
+        .bPsmSupport       = MTK_WCN_BOOL_TRUE,
+    }, 
+    {
+        .u4HwVer            = 0x8A10,
+        .cChipName         = WMT_IC_NAME_MT6628,
+        .cChipVersion      = WMT_IC_VER_E2,
+        .cPatchNameExt     = WMT_IC_PATCH_E2_EXT,
+        .eWmtHwVer        = WMTHWVER_MT6620_E2,
+        .bWorkWithoutPatch = MTK_WCN_BOOL_FALSE,
+        .bPsmSupport       = MTK_WCN_BOOL_TRUE,
+    }, 
+    {
+        .u4HwVer            = 0x8B10,
+        .cChipName         = WMT_IC_NAME_MT6628,
+        .cChipVersion      = WMT_IC_VER_E3,
+        .cPatchNameExt     = WMT_IC_PATCH_E2_EXT,
+        .eWmtHwVer        = WMTHWVER_MT6620_E3,
+        .bWorkWithoutPatch = MTK_WCN_BOOL_FALSE,
+        .bPsmSupport       = MTK_WCN_BOOL_TRUE,
+    }, 
+    {
+        .u4HwVer            = 0x8B11,
+        .cChipName         = WMT_IC_NAME_MT6628,
+        .cChipVersion      = WMT_IC_VER_E4,
+        .cPatchNameExt     = WMT_IC_PATCH_E2_EXT,
+        .eWmtHwVer        = WMTHWVER_MT6620_E4,
+        .bWorkWithoutPatch = MTK_WCN_BOOL_FALSE,
+        .bPsmSupport       = MTK_WCN_BOOL_TRUE,
+    }, 
+    {
+        .u4HwVer            = 0x8a11,
+        .cChipName         = WMT_IC_NAME_MT6628,
+        .cChipVersion      = WMT_IC_VER_E5,
+        .cPatchNameExt     = WMT_IC_PATCH_E2_EXT,
+        .eWmtHwVer        = WMTHWVER_MT6620_E5,
+        .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
+mt6628_sw_init (
+    P_WMT_HIF_CONF pWmtHifConf
+    );
+
+static INT32
+mt6628_sw_deinit (
+    P_WMT_HIF_CONF pWmtHifConf
+    );
+
+static INT32
+mt6628_pin_ctrl (
+    WMT_IC_PIN_ID id,
+    WMT_IC_PIN_STATE state,
+    UINT32 flag
+    );
+
+static INT32
+mt6628_aif_ctrl (
+    WMT_IC_PIN_STATE state,
+    UINT32 flag
+    );
+
+static INT32
+mt6628_ver_check (VOID);
+
+static const WMT_IC_INFO_S*
+mt6628_find_wmt_ic_info (
+    const UINT32 hw_ver
+    );
+
+static INT32
+wmt_stp_init_coex (VOID);
+
+#if CFG_WMT_MULTI_PATCH
+static INT32 mt6628_patch_dwn (UINT32 index);
+static INT32 mt6628_patch_info_prepare(VOID);
+#else
+static INT32 mt6628_patch_dwn (VOID);
+#endif
+
+static INT32 
+mt6628_co_clock_ctrl(WMT_CO_CLOCK on);
+static WMT_CO_CLOCK mt6628_co_clock_get(VOID);
+
+static INT32
+mt6628_crystal_triming_set (VOID);
+
+
+static MTK_WCN_BOOL mt6628_quick_sleep_flag_get(VOID);
+
+static MTK_WCN_BOOL mt6628_aee_dump_flag_get(VOID);
+
+static INT32 mt6628_set_sdio_driving(void);
+
+/*******************************************************************************
+*                            P U B L I C   D A T A
+********************************************************************************
+*/
+
+/* MT6628 Operation Function Table */
+const WMT_IC_OPS wmt_ic_ops_mt6628 = {
+    .icId = 0x6628,
+    .sw_init = mt6628_sw_init,
+    .sw_deinit = mt6628_sw_deinit,
+    .ic_pin_ctrl = mt6628_pin_ctrl,
+    .ic_ver_check = mt6628_ver_check,
+    .co_clock_ctrl = mt6628_co_clock_ctrl,
+    .is_quick_sleep  = mt6628_quick_sleep_flag_get,
+    .is_aee_dump_support = mt6628_aee_dump_flag_get,
+};
+
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+
+static INT32
+mt6628_sw_init (
+    P_WMT_HIF_CONF pWmtHifConf
+    )
+{
+    INT32 iRet = -1;
+    UINT32 u4Res = 0;
+    UCHAR evtBuf[256];
+    UINT32 ctrlPa1;
+    UINT32 ctrlPa2;
+    UINT32 hw_ver;
+#if CFG_WMT_MULTI_PATCH
+    UINT32 patch_num = 0;
+    UINT32 patch_index = 0;
+#endif
+    WMT_DBG_FUNC(" start\n");
+
+    osal_assert(NULL != gp_mt6628_info);
+    if ( (NULL == gp_mt6628_info)
+        || (NULL == pWmtHifConf)
+        ) {
+        WMT_ERR_FUNC("null pointers: gp_mt6628_info(0x%p), pWmtHifConf(0x%p)\n",
+            gp_mt6628_info, pWmtHifConf);
+        return -1;
+    }
+
+    hw_ver = gp_mt6628_info->u4HwVer;
+
+    //4 <3.1> start init for sdio
+#ifndef CFG_IC_MT6628 //For MT6628 no need to do this operation
+    if (WMT_HIF_SDIO == pWmtHifConf->hifType) {
+        wmt_lib_ps_set_idle_time(STP_PSM_SDIO_IDLE_TIME_SLEEP);
+        /* 1. enable all INT32 */
+        /* 2. disable mcu gate (only MT6628E1/E2) */
+        iRet = wmt_core_init_script(init_table_1_1, osal_array_size(init_table_1_1));
+        if (iRet) {
+            WMT_ERR_FUNC("init_table_1_1 fail:%d\n", iRet);
+            osal_assert(0);
+            return -1;
+        }
+    }
+#endif
+    //4 <3.2> start init for uart
+    if (WMT_HIF_UART == pWmtHifConf->hifType) {
+        /* init variable fields for script execution */
+        osal_memcpy(&WMT_SET_BAUD_CMD_X[5], &pWmtHifConf->au4HifConf[0], osal_sizeof(UINT32));
+        WMT_SET_BAUD_CMD_X[8] = (UCHAR)0x00;//0xC0 MTK Flow Control /* no flow control */
+        osal_memcpy(&WMT_QUERY_BAUD_EVT_X[6], &pWmtHifConf->au4HifConf[0], osal_sizeof(UINT32));
+        WMT_QUERY_BAUD_EVT_X[9] = (UCHAR)0x00; //0xC0 MTK Flow Control /* no flow control */
+
+        /* 3. Query chip baud rate (TEST-ONLY) */
+        /* 4. Query chip STP options (TEST-ONLY) */
+        /* 5. Change chip baud rate: t_baud */
+        //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;
+        }
+
+        /* 6. Set host baudrate and flow control*/
+        ctrlPa1 = pWmtHifConf->au4HifConf[0]; ctrlPa2 = 0;
+        iRet = wmt_core_ctrl(WMT_CTRL_HOST_BAUDRATE_SET, &ctrlPa1, &ctrlPa2);
+        if (iRet) {
+            WMT_ERR_FUNC("change baudrate(%d) fail(%d)\n", pWmtHifConf->au4HifConf[0], iRet);
+            return -3;
+        }
+        WMT_INFO_FUNC("WMT-CORE: change baudrate(%d) ok\n", pWmtHifConf->au4HifConf[0]);
+        
+        /* 7. Wake up chip and check event */
+//          iRet = (*kal_stp_tx_raw)(&WMT_SET_WAKEUP_WAKE_CMD_RAW[0], 1, &u4Res);
+        iRet = wmt_core_tx((PUINT8)&WMT_SET_WAKEUP_WAKE_CMD_RAW[0], 1, &u4Res, MTK_WCN_BOOL_TRUE);
+        if (iRet || (u4Res != 1)) {
+            WMT_ERR_FUNC("write raw iRet(%d) written(%d)\n", iRet, u4Res);
+            return -4;
+        }
+
+        osal_memset(evtBuf, 0, osal_sizeof(evtBuf));
+        iRet = wmt_core_rx(evtBuf, osal_sizeof(WMT_SET_WAKEUP_WAKE_EVT), &u4Res);
+#ifdef CFG_DUMP_EVT
+        WMT_DBG_FUNC("WAKEUP_WAKE_EVT read len %d [%02x,%02x,%02x,%02x,%02x,%02x]\n",
+             (INT32)u4Res, evtBuf[0], evtBuf[1], evtBuf[2], evtBuf[3], evtBuf[4], evtBuf[5]);
+#endif
+        if (iRet || (u4Res != osal_sizeof(WMT_SET_WAKEUP_WAKE_EVT))) {
+            WMT_ERR_FUNC("read WAKEUP_WAKE_EVT fail(%d)\n", iRet);
+            return -5;
+        }
+        //WMT_DBG_FUNC("WMT-CORE: read WMT_SET_WAKEUP_WAKE_EVT ok");
+
+#if CFG_CHECK_WMT_RESULT
+        if (osal_memcmp(evtBuf, WMT_SET_WAKEUP_WAKE_EVT, osal_sizeof(WMT_SET_WAKEUP_WAKE_EVT)) != 0) {
+            WMT_ERR_FUNC("WMT-CORE: write WMT_SET_WAKEUP_WAKE_CMD_RAW status fail\n");
+            return -6;
+        }
+#endif
+
+        /* 8. Query baud rate (TEST-ONLY) */
+        iRet = wmt_core_init_script(init_table_2, osal_array_size(init_table_2));
+        if (iRet) {
+            WMT_ERR_FUNC("init_table_2 fail(%d)\n", iRet);
+            return -7;
+        }
+    }
+
+    /* 9. download patch */
+#if CFG_WMT_MULTI_PATCH
+    /* 9.1 Let launcher to search patch info */
+    iRet = mt6628_patch_info_prepare();
+       if (iRet) {
+               WMT_ERR_FUNC("patch info perpare fail(%d)\n", iRet);
+               return -8;
+       }
+
+    /* 9.2 Read patch number */
+    ctrlPa1 = 0;
+    ctrlPa2 = 0;
+       wmt_core_ctrl(WMT_CTRL_GET_PATCH_NUM, &ctrlPa1, &ctrlPa2);
+       patch_num = ctrlPa1;
+       WMT_INFO_FUNC("patch total num = [%d]\n", patch_num);
+
+    /* 9.3 Multi-patch Patch download */
+    for (patch_index = 0; patch_index < patch_num; patch_index++) {
+               iRet = mt6628_patch_dwn(patch_index);
+               if (iRet) {
+                       WMT_ERR_FUNC("patch dwn fail (%d),patch_index(%d)\n", iRet, patch_index);
+               return -12;
+               }
+               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 -13;
+           }
+       }
+#else
+    /* 9.3 Patch download */
+    iRet = mt6628_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);
+    } 
+#endif // End of #if CFG_WMT_MULTI_PATCH
+
+    /* 10. 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 -9;
+    }    
+    iRet = wmt_stp_init_coex();
+    if (iRet) {
+        WMT_ERR_FUNC("init_coex fail(%d)\n", iRet);
+        return -10;
+    }
+    else {
+        WMT_INFO_FUNC("init_coex ok\n");
+    }
+       
+    mt6628_crystal_triming_set();
+
+    mt6628_set_sdio_driving();
+
+    if (WMT_HIF_UART == pWmtHifConf->hifType) {
+        /* 11. 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 -12;
+        }
+
+        /* 12. Enable host STP-UART mode */
+        ctrlPa1 = WMT_STP_CONF_MODE; ctrlPa2 = MTKSTP_UART_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-UART-FULL mode fail(%d)\n", iRet);
+            return -13;
+        }
+        WMT_INFO_FUNC("enable host STP-UART-FULL mode\n");
+        /*13. wait for 10ms, enough for chip do mechanism switch.(at least 2ms is needed)*/
+        osal_msleep(10);
+        /* 14. Query chip STP options (TEST-ONLY) */
+        /* 15. Query baud rate (stp, 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 -14;
+        }
+    }
+
+    if (WMT_CO_CLOCK_EN == mt6628_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 -15;
+        }
+    }
+       else
+       {
+           WMT_INFO_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 -15;
+        }
+       #endif
+       
+    /* 15. Set FM strap */
+    WMT_STRAP_CONF_CMD_FM_COMM[5] = (UCHAR)pWmtHifConf->au4StrapConf[0];
+    WMT_STRAP_CONF_EVT[5] = (UCHAR)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 -16;
+    }
+    WMT_INFO_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 -17;
+        }
+#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 -18;
+        } else {
+            WMT_INFO_FUNC("enable mt662x firmware coredump\n");
+        }
+    }
+    else
+    {
+        WMT_INFO_FUNC("disable mt662x firmware coredump\n");
+    }
+
+
+#if CFG_WMT_PS_SUPPORT
+    osal_assert(NULL != gp_mt6628_info);
+    if (NULL != gp_mt6628_info) {
+       if (MTK_WCN_BOOL_FALSE != gp_mt6628_info->bPsmSupport) {
+           wmt_lib_ps_enable();
+       }
+       else {
+           wmt_lib_ps_disable();
+       }
+    }
+#endif
+
+    return 0;
+}
+
+static INT32
+mt6628_sw_deinit (
+    P_WMT_HIF_CONF pWmtHifConf
+    )
+{
+    WMT_DBG_FUNC(" start\n");
+
+#if CFG_WMT_PS_SUPPORT
+    osal_assert(NULL != gp_mt6628_info);
+    if ( (NULL != gp_mt6628_info)
+        && (MTK_WCN_BOOL_FALSE != gp_mt6628_info->bPsmSupport) ) {
+           wmt_lib_ps_disable();
+       }
+#endif
+
+    gp_mt6628_info = NULL;
+
+    return 0;
+}
+
+static INT32
+mt6628_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);
+
+        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_INFO_FUNC("new state(%d) ok\n", state);
+    }
+    else {
+        WMT_WARN_FUNC("new state(%d) fail(%d)\n", state, ret);
+    }
+
+    return ret;
+}
+
+static INT32
+mt6628_gps_sync_ctrl (
+    WMT_IC_PIN_STATE state,
+    UINT32 flag
+    )
+{
+    INT32   iRet = -1;
+    UINT32  uVal = 0;
+    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 (0 != iRet)
+    {
+        WMT_ERR_FUNC("gps_sync pin ctrl failed, iRet(%d)\n", iRet);
+    }
+    // anyway, we return 0
+    return 0;
+}
+
+
+static INT32
+mt6628_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 = mt6628_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 = mt6628_gps_sync_ctrl(state, flag);
+        break;
+    default:
+        break;
+    }
+    WMT_INFO_FUNC("ret = (%d)\n" , ret);
+
+    return ret;
+}
+
+INT32 mt6628_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("MT6628: error parameter:%d\n", on);
+               iRet = -1;
+    }
+       WMT_DBG_FUNC("MT6628: Co-clock %s\n", (gCoClockEn == WMT_CO_CLOCK_DIS) ? "disabled" : "enabled");       
+       
+    return iRet;
+}
+
+static MTK_WCN_BOOL mt6628_quick_sleep_flag_get(VOID)
+{
+    return MTK_WCN_BOOL_TRUE;
+}
+
+
+static MTK_WCN_BOOL mt6628_aee_dump_flag_get(VOID)
+{
+    return MTK_WCN_BOOL_TRUE;    
+}
+
+
+WMT_CO_CLOCK mt6628_co_clock_get(VOID)
+{
+    return gCoClockEn;
+}
+
+
+
+static INT32
+mt6628_ver_check (VOID)
+{
+    UINT32 hw_ver;
+    UINT32 fw_ver;
+    INT32 iret;
+    const WMT_IC_INFO_S *p_info;
+    UINT32 ctrlPa1;
+    UINT32 ctrlPa2;
+
+    /* 1. identify chip versions: HVR(HW_VER) and FVR(FW_VER) */
+    WMT_LOUD_FUNC("MT6628: before read hw_ver (hw version)\n");
+    iret = wmt_core_reg_rw_raw(0, GEN_HVR, &hw_ver, GEN_VER_MASK);
+    if (iret) {
+        WMT_ERR_FUNC("MT6628: read hw_ver fail:%d\n", iret);
+        return -2;
+    }
+    WMT_INFO_FUNC("MT6628: read hw_ver (hw version) (0x%x)\n", hw_ver);
+
+    WMT_LOUD_FUNC("MT6628: before fw_ver (rom version) \n");
+    wmt_core_reg_rw_raw(0, GEN_FVR, &fw_ver, GEN_VER_MASK);
+    if (iret) {
+        WMT_ERR_FUNC("MT6628: read fw_ver fail:%d\n", iret);
+        return -2;
+    }
+    WMT_INFO_FUNC("MT6628: read fw_ver (rom version) (0x%x)\n", fw_ver);
+
+    p_info = mt6628_find_wmt_ic_info(hw_ver);
+    if (NULL == p_info) {
+        WMT_ERR_FUNC("MT6628: hw_ver(0x%x) find wmt ic info fail\n");
+        return -3;
+    }
+
+    WMT_INFO_FUNC("MT6628: wmt ic info: %s.%s (0x%x, WMTHWVER:%d, patch_ext:%s)\n",
+        p_info->cChipName, p_info->cChipVersion,
+        p_info->u4HwVer, p_info->eWmtHwVer,
+        p_info->cPatchNameExt);
+
+    /* hw id & version */
+    ctrlPa1 = (0x00006628UL << 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("MT6628: WMT_CTRL_HWIDVER_SET fail(%d)\n", iret);
+    }
+
+    gp_mt6628_info = p_info;
+    return 0;
+}
+
+static const WMT_IC_INFO_S*
+mt6628_find_wmt_ic_info (
+    const UINT32 hw_ver
+    )
+{
+    /* match chipversion with u4HwVer item in mt6628_info_table */
+    const UINT32 size = osal_array_size(mt6628_info_table);
+    INT32 index;
+
+    /* 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 != mt6628_info_table[index].u4HwVer) /* full match */
+        ) {
+        --index;
+    }
+    if (0 <= index) {
+        WMT_INFO_FUNC("found ic info(0x%x) by full match! index:%d\n", hw_ver, index);
+        return &mt6628_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(mt6628_info_table[index].u4HwVer))
+        ) {
+        --index;
+    }
+    if (0 <= index) {
+        WMT_INFO_FUNC("MT6628: found ic info for hw_ver(0x%x) by major num! index:%d\n", hw_ver, index);
+        return &mt6628_info_table[index];
+    }
+
+    WMT_ERR_FUNC("MT6628: find no ic info for hw_ver(0x%x) by full match nor major num match!\n", hw_ver);
+    return NULL;
+}
+
+
+static INT32
+wmt_stp_init_coex (VOID)
+{
+    INT32 iRet;
+    UINT32 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;
+}
+
+
+static INT32 mt6628_set_sdio_driving(void)
+{
+    INT32 ret = 0;
+
+    UINT32 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]= (UCHAR)((drv_val & 0x00000077UL) >> 0);  // DAT0 and DAT1
+    sdio_driving_table[0].cmd[13]= (UCHAR)((drv_val & 0x00007700UL) >> 8);  // DAT2 and DAT3
+    sdio_driving_table[0].cmd[14]= (UCHAR)((drv_val & 0x00070000UL) >> 16); // CMD
+
+    ret = wmt_core_init_script(sdio_driving_table, sizeof(sdio_driving_table)/sizeof(sdio_driving_table[0]));
+
+    return ret;
+}
+
+
+static INT32
+mt6628_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;
+    CHAR cCrystalTimingOffset = 0x0;
+       UCHAR 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("MT6628: WMT_CTRL_CRYSTAL_TRIMING_GET fail:%d \n", iRet);
+               bIsNvramExist = MTK_WCN_BOOL_FALSE;
+               bIsCrysTrimEnabled = MTK_WCN_BOOL_FALSE;
+               cCrystalTimingOffset = 0x0;
+               cCrystalTiming = 0x0;           
+               iRet = -1;
+    }
+       else
+       {
+           WMT_DBG_FUNC("MT6628: nvram pBuf(0x%08x), bufLen(%d)\n", pbuf, bufLen);
+               if (bufLen < (uCryTimOffset + 1))
+               {
+                   WMT_ERR_FUNC("MT6628: nvram len(%d) too short, crystalTimging value offset(%d)\n", 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 = (UCHAR)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("MT6628: WMT_CTRL_CRYSTAL_TRIMING_PUT fail:%d \n", iRet);
+                       iRet = -2;
+        }
+               else
+               {
+                   WMT_DBG_FUNC("MT6628: WMT_CTRL_CRYSTAL_TRIMING_PUT succeed\n");
+               }
+       }
+    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;    
+}
+
+
+#if CFG_WMT_MULTI_PATCH
+static INT32 mt6628_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
+mt6628_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];
+       UCHAR addressByte[4];
+    PCHAR cDataTime = NULL;
+    /*PCHAR 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_mt6628_info) {
+        WMT_ERR_FUNC("null gp_mt6628_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] = (UINT32)&gFullPatchName;
+       ctrlData.au4CtrlData[2] = (UINT32)&addressByte;
+       iRet = wmt_ctrl(&ctrlData);
+       WMT_INFO_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] = (UINT32)NULL;
+       ctrlData.au4CtrlData[1] = (UINT32)&gFullPatchName;
+       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';
+    if (index == 0) {
+        WMT_INFO_FUNC("===========================================\n");
+        WMT_INFO_FUNC("[Combo Patch] Built Time = %s\n", cDataTime);
+        WMT_INFO_FUNC("[Combo Patch] Hw Ver = 0x%x\n", ((u2HwVer & 0x00ff) << 8) | ((u2HwVer & 0xff00) >> 8));
+        WMT_INFO_FUNC("[Combo Patch] Sw Ver = 0x%x\n", ((u2SwVer & 0x00ff) << 8) | ((u2SwVer & 0xff00) >> 8));
+        WMT_INFO_FUNC("[Combo Patch] Ph Ver = 0x%04x\n",  ((u4PatchVer & 0xff000000) >> 24) | ((u4PatchVer & 0x00ff0000) >> 16));
+        WMT_INFO_FUNC("[Combo Patch] Platform = %c%c%c%c\n", patchHdr->ucPLat[0],
+            patchHdr->ucPLat[1], patchHdr->ucPLat[2], patchHdr->ucPLat[3]);
+        WMT_INFO_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 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_INFO_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 result error 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], 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_INFO_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
+mt6628_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];
+    PCHAR cDataTime = NULL;
+    /*PCHAR 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_mt6628_info) {
+        WMT_ERR_FUNC("null gp_mt6628_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_INFO_FUNC("===========================================\n");
+    WMT_INFO_FUNC("[Combo Patch] Built Time = %s\n", cDataTime);
+    WMT_INFO_FUNC("[Combo Patch] Hw Ver = 0x%x\n", ((u2HwVer & 0x00ff) << 8) | ((u2HwVer & 0xff00) >> 8));
+    WMT_INFO_FUNC("[Combo Patch] Sw Ver = 0x%x\n", ((u2SwVer & 0x00ff) << 8) | ((u2SwVer & 0xff00) >> 8));
+    WMT_INFO_FUNC("[Combo Patch] Ph Ver = 0x%04x\n",  ((u4PatchVer & 0xff000000) >> 24) | ((u4PatchVer & 0x00ff0000) >> 16));
+    WMT_INFO_FUNC("[Combo Patch] Platform = %c%c%c%c\n", patchHdr->ucPLat[0],
+        patchHdr->ucPLat[1], patchHdr->ucPLat[2], patchHdr->ucPLat[3]);
+    WMT_INFO_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 result error 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], 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_INFO_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/mtk_wcn_combo/common/core/wmt_lib.c b/drivers/mtk_wcn_combo/common/core/wmt_lib.c
new file mode 100755 (executable)
index 0000000..17b70fe
--- /dev/null
@@ -0,0 +1,1842 @@
+/*! \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_dbg.h"
+
+#include "wmt_dev.h"
+#include "wmt_lib.h"
+#include "wmt_conf.h"
+#include "wmt_core.h"
+#include "wmt_plat.h"
+#include "wmt_plat_stub.h"
+
+#include "stp_core.h"
+#include "btm_core.h"
+#include "psm_core.h"
+#include "stp_sdio.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 = NULL;
+#endif
+
+
+/*******************************************************************************
+*                            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
+    );
+MTK_WCN_BOOL wmt_lib_hw_state_show(VOID);
+
+
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+
+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();
+#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));
+
+#if 0
+    iRet = wmt_conf_read_file();
+    if (iRet) {
+        WMT_ERR_FUNC("read wmt config file fail(%d)\n", iRet);
+        return -1;
+    }
+#endif
+
+    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->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_MT6620_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)
+    {
+        
+        PWR_SEQ_TIME pwrSeqTime;
+        pwrSeqTime.ldoStableTime = gDevWmt.rWmtGenConf.pwr_on_ldo_slot;
+        pwrSeqTime.rstStableTime = gDevWmt.rWmtGenConf.pwr_on_rst_slot;
+        pwrSeqTime.onStableTime = gDevWmt.rWmtGenConf.pwr_on_on_slot;
+        pwrSeqTime.offStableTime = gDevWmt.rWmtGenConf.pwr_on_off_slot;
+        pwrSeqTime.rtcStableTime = gDevWmt.rWmtGenConf.pwr_on_rtc_slot;
+        WMT_INFO_FUNC("set pwr on seq par to hw conf\n");
+        WMT_INFO_FUNC("ldo(%d)rst(%d)on(%d)off(%d)rtc(%d)\n", pwrSeqTime.ldoStableTime, pwrSeqTime.rstStableTime, pwrSeqTime.onStableTime, pwrSeqTime.offStableTime, pwrSeqTime.rtcStableTime);
+        iRet = wmt_plat_init(&pwrSeqTime);
+    }
+    else
+    {
+        WMT_INFO_FUNC("no pwr on seq par found\n");
+        iRet = wmt_plat_init(NULL);
+    }
+    if (iRet) {
+        WMT_ERR_FUNC("wmt_plat_init() fail(%d)\n", iRet);
+        return -3;
+    }
+       wmt_plat_stub_init();
+
+#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_lib_plat_irq_cb_reg(wmt_lib_ps_irq_cb);
+
+       /*5. register audio if control callback to WMT-PLAT*/
+       wmt_lib_plat_aif_cb_reg(wmt_lib_set_aif);
+
+       
+    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->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));
+
+    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 (
+    UCHAR *cPatchName
+    )
+{
+    osal_strncpy(gDevWmt.cPatchName, cPatchName, NAME_MAX);
+    return 0;
+}
+#if WMT_PLAT_ALPS    
+extern PCHAR wmt_uart_port_desc; // defined in mtk_wcn_cmb_stub_alps.cpp
+#endif
+INT32
+wmt_lib_set_uart_name(
+    CHAR *cUartName
+)
+{
+#if WMT_PLAT_ALPS
+
+    WMT_INFO_FUNC("orig uart: %s\n", wmt_uart_port_desc);
+#endif
+    osal_strncpy(gDevWmt.cUartName, cUartName, NAME_MAX);
+#if WMT_PLAT_ALPS
+    wmt_uart_port_desc = gDevWmt.cUartName;
+    WMT_INFO_FUNC("new uart: %s\n", wmt_uart_port_desc);
+#endif
+    return 0;
+}
+
+INT32
+wmt_lib_set_hif (
+    ULONG hifconf
+    )
+{
+    UINT32 val;
+    P_WMT_HIF_CONF pHif = &gDevWmt.rWmtHifConf;
+
+    val = hifconf & 0xF;
+    if (STP_UART_FULL == val) {
+        pHif->hifType = WMT_HIF_UART;
+               pHif->uartFcCtrl = ((hifconf & 0xc) >> 2);
+        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 {
+        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_INFO_FUNC("new hifType:%d, fcCtrl:%d, baud:%d, fm:%d \n",
+        pHif->hifType,
+        pHif->uartFcCtrl,
+        pHif->au4HifConf[0],
+        pHif->au4StrapConf[0]);
+    return 0;
+}
+
+
+P_WMT_HIF_CONF
+wmt_lib_get_hif (VOID)
+{
+    return &gDevWmt.rWmtHifConf;
+}
+
+UCHAR*
+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)
+    {
+        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;
+
+    lxop = wmt_lib_get_free_op();
+    if (!lxop)
+    {
+        WMT_WARN_FUNC("get_free_lxop fail \n");
+        return MTK_WCN_BOOL_FALSE;
+    }
+
+    lxop->op.opId = WMT_OPID_PWR_SV;
+    lxop->op.au4OpData[0] = action;
+    lxop->op.au4OpData[1] = (UINT32) mtk_wcn_stp_psm_notify_stp;
+    u4Wait = 0;
+    bRet = wmt_lib_put_act_op(lxop);
+    return bRet;
+}
+
+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)
+{
+    return wmt_lib_ps_action(HOST_AWAKE);
+}
+//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);
+        }
+        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");
+            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);
+            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)
+{
+    return wmt_core_is_quick_ps_support();
+}
+
+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));
+    }
+    else {
+        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 (0x%x) 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 (0x%x) 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;
+    }
+
+    /* 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);
+
+    if (NULL != pDevWmt) {
+        pOp = wmt_lib_get_op(&pDevWmt->rFreeOpQ);
+        if (pOp) {
+            osal_memset(&pOp->op, 0, osal_sizeof(pOp->op));
+        }
+        return pOp;
+    }
+    else {
+        return NULL;
+    }
+}
+
+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;
+
+    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())
+        {
+            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)
+        {
+            WMT_ERR_FUNC("wait completion timeout\n");
+            // TODO: how to handle it? retry?
+        }
+        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;
+
+    return;
+}
+#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;
+    
+}
+
+
+UCHAR* 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_MT6620_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_MT6620_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] = (UINT32)&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;
+    }
+    else {
+        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] = (UINT32)&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;
+    }
+    else {
+        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;
+    UCHAR *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 ((pOp = wmt_lib_get_op(&pDevWmt->rActiveOpQ))) {
+        osal_signal_init(&(pOp->signal));
+        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]));
+    }*/
+    return;
+}
+
+
+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;
+    }
+    else {
+        WMT_DBG_FUNC("OPID(WMT_OPID_SDIO_CTRL)ok\n");
+    }
+    return 0;
+}
+
+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;
+    }
+    else {
+        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;
+    }
+    else {
+        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;
+    }
+    else {
+        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;
+    INT32 retries = RETRYTIMES;
+    P_DEV_WMT pDevWmt = &gDevWmt;
+    P_OSAL_OP pOp;
+    UCHAR *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;
+    }
+
+    if(bRet == MTK_WCN_BOOL_FALSE){
+        WMT_INFO_FUNC("[whole chip reset] fail! retries = %d\n", RETRYTIMES-retries);
+        retval = WMTRSTRET_FAIL;
+        goto rstDone;
+    } else {
+        WMT_INFO_FUNC("[whole chip reset] ok! retries = %d\n", RETRYTIMES-retries);
+    }
+
+
+    //<5> RESET_END notification
+    bRet = wmt_cdev_rstmsg_snd(WMTRSTMSG_RESET_END);
+    if(bRet == MTK_WCN_BOOL_FALSE){
+        WMT_ERR_FUNC("[whole chip reset] fail at wmt_lib_rstmsg_snd! \n");
+        retval = WMTRSTRET_FAIL;
+        goto rstDone;
+    }
+
+    retval = WMTRSTRET_SUCCESS;
+rstDone:
+    osal_clear_bit(WMT_STAT_RST_ON, &pDevWmt->state);
+    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()
+{
+    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(ULONG 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;
+    } else {
+        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;
+    } else {
+        WMT_ERR_FUNC("Invalid pointer\n");
+        return NULL;
+       }
+}
+
+INT32 wmt_lib_merge_if_flag_ctrl(UINT32 enable)
+{
+#if WMT_PLAT_ALPS
+    return wmt_plat_merge_if_flag_ctrl(enable);
+#endif
+}
+
+
+INT32 wmt_lib_merge_if_flag_get(UINT32 enable)
+{
+#if WMT_PLAT_ALPS
+    return wmt_plat_merge_if_flag_get();
+#endif
+}
+
diff --git a/drivers/mtk_wcn_combo/common/include/mtk_wcn_cmb_hw.h b/drivers/mtk_wcn_combo/common/include/mtk_wcn_cmb_hw.h
new file mode 100755 (executable)
index 0000000..4724dbf
--- /dev/null
@@ -0,0 +1,90 @@
+/*! \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_HW_H_
+#define _MTK_WCN_CMB_HW_H_
+
+#include "osal_typedef.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 struct _PWR_SEQ_TIME_
+{
+    UINT32 rtcStableTime;
+    UINT32 ldoStableTime;
+    UINT32 rstStableTime;
+    UINT32 offStableTime;
+    UINT32 onStableTime;
+}PWR_SEQ_TIME, *P_PWR_SEQ_TIME;
+
+
+/*******************************************************************************
+*                            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
+********************************************************************************
+*/
+
+extern INT32 mtk_wcn_cmb_hw_pwr_off (VOID);
+extern INT32 mtk_wcn_cmb_hw_pwr_on (VOID);
+extern INT32 mtk_wcn_cmb_hw_rst (VOID);
+extern INT32 mtk_wcn_cmb_hw_init (P_PWR_SEQ_TIME pPwrSeqTime);
+extern INT32 mtk_wcn_cmb_hw_deinit (VOID);
+extern INT32 mtk_wcn_cmb_hw_state_show(VOID);
+
+
+#endif /* _MTK_WCN_CMB_HW_H_ */
+
diff --git a/drivers/mtk_wcn_combo/common/include/stp_exp.h b/drivers/mtk_wcn_combo/common/include/stp_exp.h
new file mode 100755 (executable)
index 0000000..97c1d97
--- /dev/null
@@ -0,0 +1,227 @@
+/*! \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"
+
+/*******************************************************************************
+*                         C O M P I L E R   F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                                 M A C R O S
+********************************************************************************
+*/
+
+#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 MTKSTP_MAX_TASK_NUM (7)
+
+#define MTKSTP_BUFFER_SIZE  (16384) //Size of RX Queue
+
+
+
+/*******************************************************************************
+*                    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 (*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,
+    STP_MAX_IF_TX
+}ENUM_STP_TX_IF_TYPE;
+
+/*******************************************************************************
+*                            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
+********************************************************************************
+*/
+
+/*****************************************************************************
+* 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 UINT8 *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 INT32 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
+*  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_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_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);
+
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+
+#endif /* _WMT_EXP_H_ */
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/drivers/mtk_wcn_combo/common/include/wmt.h b/drivers/mtk_wcn_combo/common/include/wmt.h
new file mode 100755 (executable)
index 0000000..f493187
--- /dev/null
@@ -0,0 +1,8 @@
+
+#ifndef _MTKWMT_H_
+#define _MTKWMT_H_
+#include "wmt_core.h"
+
+
+
+#endif /*_MTKWMT_H_*/
diff --git a/drivers/mtk_wcn_combo/common/include/wmt_exp.h b/drivers/mtk_wcn_combo/common/include/wmt_exp.h
new file mode 100755 (executable)
index 0000000..466c97f
--- /dev/null
@@ -0,0 +1,257 @@
+/*! \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 <mach/mtk_wcn_cmb_stub.h>
+#include "osal.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...)   if (gWmtDbgLvl >= WMT_LOG_LOUD) { osal_dbg_print(DFT_TAG "[L]%s:"  fmt, __FUNCTION__ ,##arg);}
+#define WMT_INFO_FUNC(fmt, arg...)   if (gWmtDbgLvl >= WMT_LOG_INFO) { osal_info_print(DFT_TAG "[I]%s:"  fmt, __FUNCTION__ ,##arg);}
+#define WMT_WARN_FUNC(fmt, arg...)   if (gWmtDbgLvl >= WMT_LOG_WARN) { osal_warn_print(DFT_TAG "[W]%s:"  fmt, __FUNCTION__ ,##arg);}
+#define WMT_ERR_FUNC(fmt, arg...)    if (gWmtDbgLvl >= WMT_LOG_ERR) { osal_err_print(DFT_TAG "[E]%s(%d):"  fmt, __FUNCTION__ , __LINE__, ##arg);}
+#define WMT_DBG_FUNC(fmt, arg...)    if (gWmtDbgLvl >= WMT_LOG_DBG) { osal_dbg_print(DFT_TAG "[D]%s:"  fmt, __FUNCTION__ ,##arg);}
+#define WMT_TRC_FUNC(f)              if (gWmtDbgLvl >= WMT_LOG_DBG) { osal_dbg_print(DFT_TAG "<%s> <%d>\n", __FUNCTION__, __LINE__);}
+#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
+
+/*******************************************************************************
+*                              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_WMT_PS_SUPPORT 1 /* moved from wmt_lib.h */
+/*******************************************************************************
+*                             D A T A   T Y P E S
+********************************************************************************
+*/
+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_COREDUMP = 9,
+    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_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_E7 = 0x6,
+    WMTHWVER_MT6620_MAX,
+    WMTHWVER_INVALID = 0xff
+} ENUM_WMTHWVER_TYPE_T, *P_ENUM_WMTHWVER_TYPE_T;
+
+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;
+
+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 enum _ENUM_WMTRSTMSG_TYPE_T{
+    WMTRSTMSG_RESET_START = 0x0,
+    WMTRSTMSG_RESET_END = 0x1,
+    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. */
+    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);
+
+#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
+
+/*******************************************************************************
+*                            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
+********************************************************************************
+*/
+/*subsystem function ctrl APIs*/
+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 (
+    VOID
+    );
+
+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);
+
+extern INT32
+mtk_wcn_wmt_chipid_query (VOID);
+
+
+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);
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+
+#endif /* _WMT_EXP_H_ */
+
+
+
+
+
+
+
diff --git a/drivers/mtk_wcn_combo/common/include/wmt_plat.h b/drivers/mtk_wcn_combo/common/include/wmt_plat.h
new file mode 100755 (executable)
index 0000000..3cf5440
--- /dev/null
@@ -0,0 +1,212 @@
+/*! \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 "osal.h"
+#include <mach/mtk_wcn_cmb_stub.h>
+#include "mtk_wcn_cmb_hw.h"
+
+
+/*******************************************************************************
+*                         C O M P I L E R   F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                                 M A C R O S
+********************************************************************************
+*/
+
+
+
+
+#if (CONFIG_ARCH_MT6589)
+    #if defined(MTK_MERGE_INTERFACE_SUPPORT) && defined(MT6628)
+        #define MTK_WCN_CMB_MERGE_INTERFACE_SUPPORT 1
+       #else
+           #define MTK_WCN_CMB_MERGE_INTERFACE_SUPPORT 0
+    #endif
+#else
+    #define MTK_WCN_CMB_MERGE_INTERFACE_SUPPORT 0
+#endif
+
+
+/*******************************************************************************
+*                              C O N S T A N T S
+********************************************************************************
+*/
+
+#if 0 /* [GeorgeKuo] remove COMBO_AUDIO FLAG */
+#define COMBO_AUDIO_BT_MASK (0x1UL)
+#define COMBO_AUDIO_BT_PCM_ON (0x1UL << 0)
+#define COMBO_AUDIO_BT_PCM_OFF (0x0UL << 0)
+
+#define COMBO_AUDIO_FM_MASK (0x2UL)
+#define COMBO_AUDIO_FM_LINEIN (0x0UL << 1)
+#define COMBO_AUDIO_FM_I2S (0x1UL << 1)
+
+#define COMBO_AUDIO_PIN_MASK     (0x4UL)
+#define COMBO_AUDIO_PIN_SHARE    (0x1UL << 2)
+#define COMBO_AUDIO_PIN_SEPARATE (0x0UL << 2)
+#endif
+
+/*******************************************************************************
+*                             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_LDO = 0,
+    PIN_PMU = 1,
+    PIN_RTC = 2,
+    PIN_RST = 3,
+    PIN_BGF_EINT = 4,
+    PIN_WIFI_EINT = 5,
+    PIN_ALL_EINT = 6,
+    PIN_UART_GRP = 7,
+    PIN_PCM_GRP = 8,
+    PIN_I2S_GRP = 9,
+    PIN_SDIO_GRP = 10,
+    PIN_GPS_SYNC = 11,
+    PIN_GPS_LNA = 12,
+    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 VOID (*irq_cb)(VOID);
+typedef INT32 (*device_audio_if_cb) (CMB_STUB_AIF_X aif, MTK_WCN_BOOL share);
+
+
+/*******************************************************************************
+*                    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
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+*                           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 (P_PWR_SEQ_TIME pPwrSeqTime);
+
+INT32
+wmt_plat_deinit (VOID);
+
+INT32
+wmt_plat_irq_ctrl (
+    ENUM_FUNC_STATE state
+    );
+
+INT32
+wmt_plat_pwr_ctrl (
+    ENUM_FUNC_STATE state
+    );
+
+INT32
+wmt_plat_ps_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_sdio_ctrl (
+    UINT32 sdioPortNum,
+    ENUM_FUNC_STATE on
+    );
+
+
+INT32
+wmt_plat_wake_lock_ctrl(
+    ENUM_WL_OP opId
+    );
+
+VOID wmt_lib_plat_irq_cb_reg (irq_cb bgf_irq_cb);
+
+INT32
+wmt_plat_audio_ctrl (
+    CMB_STUB_AIF_X state,
+    CMB_STUB_AIF_CTRL ctrl
+    );
+
+VOID wmt_lib_plat_aif_cb_reg (device_audio_if_cb aif_ctrl_cb);
+
+INT32
+wmt_plat_merge_if_flag_ctrl (UINT32 enagle);
+
+INT32
+wmt_plat_merge_if_flag_get (VOID);
+
+
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+
+#endif /* _WMT_PLAT_H_ */
+
diff --git a/drivers/mtk_wcn_combo/common/include/wmt_plat_stub.h b/drivers/mtk_wcn_combo/common/include/wmt_plat_stub.h
new file mode 100755 (executable)
index 0000000..ba2f26e
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef _WMT_PLAT_STUB_H_
+#define _WMT_PLAT_STUB_H_
+
+
+INT32
+wmt_plat_audio_ctrl (
+    CMB_STUB_AIF_X state,
+    CMB_STUB_AIF_CTRL ctrl
+    );
+
+INT32 wmt_plat_stub_init (void);
+
+#endif /*_WMT_PLAT_STUB_H_*/
\ No newline at end of file
diff --git a/drivers/mtk_wcn_combo/common/linux/hif_sdio.c b/drivers/mtk_wcn_combo/common/linux/hif_sdio.c
new file mode 100755 (executable)
index 0000000..b303187
--- /dev/null
@@ -0,0 +1,2491 @@
+/*
+** $Id: $
+*/
+
+/*! \file   "hif_sdio.c"
+ * \brief
+ *
+ * detailed description
+*/
+
+/*
+** $Log: $
+ *
+ * 07 25 2010 george.kuo
+ *
+ * Move hif_sdio driver to linux directory.
+ *
+ * 07 23 2010 george.kuo
+ *
+ * Add MT6620 driver source tree
+ * , including char device driver (wmt, bt, gps), stp driver, interface driver (tty ldisc and hif_sdio), and bt hci driver.
+**
+**
+*/
+
+
+/*******************************************************************************
+*                         C O M P I L E R   F L A G S
+********************************************************************************
+*/
+#define HIF_SDIO_UPDATE (1)
+#if (WMT_PLAT_APEX==1)
+#define HIF_SDIO_SUPPORT_SUSPEND (1)
+#else
+#define HIF_SDIO_SUPPORT_SUSPEND (0)
+#endif
+
+/*******************************************************************************
+*                    E X T E R N A L   R E F E R E N C E S
+********************************************************************************
+*/
+
+
+
+#include "hif_sdio.h"
+#include "hif_sdio_chrdev.h"
+
+#if 0
+extern void mmc_power_up_ext(struct mmc_host *host);
+extern void mmc_power_off_ext(struct mmc_host *host);
+#else
+#define mmc_power_up_ext(x)
+#define mmc_power_off_ext(x)
+
+#endif
+/*******************************************************************************
+*                              C O N S T A N T S
+********************************************************************************
+*/
+//#define DRV_NAME "[hif_sdio]"
+
+/*******************************************************************************
+*                             D A T A   T Y P E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                                 M A C R O S
+********************************************************************************
+*/
+/*!
+ * \brief A macro used to generate hif_sdio client's context
+ *
+ * Generate a context for hif_sdio client based on the following input parameters
+ * |<-card id (16bits)->|<-block size in unit of 256 bytes(8 bits)->|<-function number(4bits)->|<-index(4bits)->|
+ *
+ * \param manf      the 16 bit manufacturer id
+ * \param card      the 16 bit card id
+ * \param func      the 16 bit function number
+ * \param b_sz    the 16 bit function block size
+ */
+#define CLTCTX(cid, func, blk_sz, idx) \
+    (MTK_WCN_HIF_SDIO_CLTCTX)( (((UINT32)(cid) & 0xFFFFUL) << 16) | \
+        (((UINT32)(func) & 0xFUL) << 4) | \
+        (((UINT32)(blk_sz) & 0xFF00UL) << 0) | \
+        (((UINT32)idx & 0xFUL) << 0) )
+
+/*!
+ * \brief A set of macros used to get information out of an hif_sdio client context
+ *
+ * Generate a context for hif_sdio client based on the following input parameters
+ */
+#define CLTCTX_CID(ctx) (((ctx) >> 16) & 0xFFFF)
+#define CLTCTX_FUNC(ctx) (((ctx) >> 4) & 0xF)
+#define CLTCTX_BLK_SZ(ctx) (((ctx) >> 0) & 0xFF00)
+#define CLTCTX_IDX(ctx) ((ctx) & 0xF)
+#define CLTCTX_IDX_VALID(idx) ((idx >= 0) && (idx < CFG_CLIENT_COUNT))
+
+/*******************************************************************************
+*                   F U N C T I O N   D E C L A R A T I O N S
+********************************************************************************
+*/
+#if HIF_SDIO_SUPPORT_SUSPEND
+static int hif_sdio_suspend (
+    struct device *dev
+    );
+
+static int hif_sdio_resume (
+    struct device *dev
+    );
+#endif
+static int hif_sdio_probe (
+    struct sdio_func *func,
+    const struct sdio_device_id *id
+    );
+
+static void hif_sdio_remove (
+    struct sdio_func *func
+    );
+
+static void hif_sdio_irq (
+    struct sdio_func *func
+    );
+
+static int hif_sdio_clt_probe_func (
+    MTK_WCN_HIF_SDIO_REGISTINFO *registinfo_p,
+    INT8 probe_idx
+    );
+
+static void hif_sdio_clt_probe_worker(
+    struct work_struct *work
+    );
+
+static int hif_sdio_find_probed_list_index_by_func(
+    struct sdio_func *func
+    );
+
+#if 0 // TODO:[ChangeFeature][George] remove obsolete function?
+static int hif_sdio_find_probed_list_index_by_clt_index(
+    INT32 clt_index
+    );
+#endif
+
+static int hif_sdio_find_probed_list_index_by_id_func(
+    UINT16 vendor,
+    UINT16 device,
+    UINT16 func_num
+    );
+
+static void hif_sdio_init_clt_list(
+    INT32 index
+    );
+
+static int hif_sdio_find_clt_list_index (
+    UINT16 vendor,
+    UINT16 device,
+    UINT16 func_num
+    );
+
+static int hif_sdio_check_supported_sdio_id(
+    UINT16 vendor,
+    UINT16 device
+    );
+
+static int hif_sdio_check_duplicate_sdio_id(
+    UINT16 vendor,
+    UINT16 device,
+    UINT16 func_num
+    );
+
+static int hif_sdio_add_clt_list(
+    INT32*  clt_index_p,
+    const MTK_WCN_HIF_SDIO_CLTINFO *pinfo,
+    UINT32 tbl_index
+    );
+
+static INT32 hif_sdio_stp_on(
+    void
+    );
+
+static INT32 hif_sdio_stp_off(
+    void
+    );
+
+static INT32 hif_sdio_wifi_on(
+    void
+    );
+
+static INT32 hif_sdio_wifi_off(
+    void
+    );
+
+/*******************************************************************************
+*                           P R I V A T E   D A T A
+********************************************************************************
+*/
+
+/* 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) },
+    { /* end: all zeroes */ },
+};
+
+#if HIF_SDIO_SUPPORT_SUSPEND
+static const struct dev_pm_ops mtk_sdio_pmops = {
+    .suspend = hif_sdio_suspend,
+    .resume = hif_sdio_resume,
+};
+#endif
+
+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 = hif_sdio_probe,
+    .remove = hif_sdio_remove,
+#if HIF_SDIO_SUPPORT_SUSPEND
+    .drv = {
+       .pm = &mtk_sdio_pmops,
+    },
+#endif
+};
+
+/* Registered client driver list */
+/* static list g_hif_sdio_clt_drv_list */
+static MTK_WCN_HIF_SDIO_REGISTINFO g_hif_sdio_clt_drv_list[CFG_CLIENT_COUNT];
+
+/* MMC probed function list */
+/* static list g_hif_sdio_probed_func_list */
+static MTK_WCN_HIF_SDIO_PROBEINFO g_hif_sdio_probed_func_list[CFG_CLIENT_COUNT];
+
+/* spin lock info for g_hif_sdio_clt_drv_list and g_hif_sdio_probed_func_list */
+static MTK_WCN_HIF_SDIO_LOCKINFO g_hif_sdio_lock_info;
+
+/* reference count, debug information? */
+static int gRefCount;
+static int (*fp_wmt_tra_sdio_update)(void) = NULL;
+
+
+/*******************************************************************************
+*                            P U B L I C   D A T A
+********************************************************************************
+*/
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("MediaTek Inc WCN_SE_CS3");
+MODULE_DESCRIPTION("MediaTek MT6620 HIF SDIO Driver");
+
+MODULE_DEVICE_TABLE(sdio, mtk_sdio_id_tbl);
+
+UINT32 gHifSdioDbgLvl = HIF_SDIO_LOG_INFO;
+
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+
+#if (WMT_PLAT_APEX==0)
+extern int mtk_wcn_sdio_irq_flag_set (int falg);
+#else
+int mtk_wcn_sdio_irq_flag_set (int falg)
+{
+       return 0;
+}
+#endif
+
+
+
+/*!
+ * \brief register the callback funciton for record the timestamp of sdio access 
+ *
+ * \param  callback function
+ *
+ * \retval -EINVAL, when registered callback is invalid
+ * \retval 0, when registered callback is valid
+ */
+extern INT32 mtk_wcn_hif_sdio_update_cb_reg(int (*ts_update)(void))
+{
+    if(ts_update){
+        fp_wmt_tra_sdio_update = ts_update;
+        return 0;
+    }
+    else {
+        return -EINVAL;
+    }
+}
+
+
+/*!
+ * \brief update the accessing time of SDIO via callback function
+ *
+ * \param  void
+ *
+ * \retval -EINVAL, when callback is not registered
+ * \retval returned value of callback
+ */
+static INT32 wmt_tra_sdio_update(VOID)
+{
+    if(fp_wmt_tra_sdio_update){     
+        return (*fp_wmt_tra_sdio_update)();
+    } 
+    else {
+        //HIF_SDIO_WARN_FUNC("wmt_tra_sdio_update == NULL\n");    
+        return -EINVAL;
+    }   
+}
+/*!
+ * \brief Translate CLTCTX into a pointer to struct sdio_func if it is valid
+ *
+ * Translate a CLTCTX into a pointer to struct sdio_func if it is
+ *  1) probed by mmc_core, and
+ *  2) client driver is registered, and
+ *  3) clt_idx of client driver is valid
+ *
+ * \param ctx a context provided by client driver
+ *
+ * \retval null if any condition is not valie
+ * \retval a pointer to a struct sdio_func mapped by provided ctx
+ */
+static inline struct sdio_func* hif_sdio_ctx_to_func (
+    MTK_WCN_HIF_SDIO_CLTCTX ctx)
+{
+    UINT32 probe_index;
+
+    //4 <1> check if ctx is valid, registered, and probed
+    probe_index = CLTCTX_IDX(ctx);
+    if (unlikely(!CLTCTX_IDX_VALID(probe_index)))   /* invalid index in CLTCTX */
+    {
+        HIF_SDIO_WARN_FUNC("invalid ctx(0x%x)\n", ctx);
+        return NULL;
+    }
+    else
+    {
+        if (unlikely(g_hif_sdio_probed_func_list[probe_index].clt_idx < 0))   /* the client has not been registered */
+        {
+            HIF_SDIO_WARN_FUNC("can't find client idx in probed list!ctx(0x%x) prob_idx(%d) clt_idx(%d)\n",
+                ctx, probe_index, g_hif_sdio_probed_func_list[probe_index].clt_idx);
+            return NULL;
+        }
+    }
+    return g_hif_sdio_probed_func_list[probe_index].func;
+}
+
+/*!
+ * \brief MTK hif sdio client registration function
+ *
+ * Client uses this function to register itself to hif_sdio driver
+ *
+ * \param pinfo a pointer of client's information
+ *
+ * \retval 0 register successfully
+ * \retval < 0 list error code here
+ */
+INT32 mtk_wcn_hif_sdio_client_reg (
+    const MTK_WCN_HIF_SDIO_CLTINFO *pinfo
+    )
+{
+    INT32   ret = -HIF_SDIO_ERR_FAIL;
+    INT32   clt_index = -1;
+    UINT32  i   = 0;
+    UINT32  j   = 0;
+    MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO *clt_probe_worker_info = 0;
+
+    HIF_SDIO_INFO_FUNC("start!\n");
+
+    //4 <1> check input pointer is valid
+    HIF_SDIO_ASSERT( pinfo );
+
+    //4 <2> check if input parameters are all supported and valid
+    for ( i=0; i<pinfo->func_tbl_size; i++ )
+    {
+        ret = hif_sdio_check_supported_sdio_id( pinfo->func_tbl[i].manf_id, pinfo->func_tbl[i].card_id );
+        if(ret)
+        {
+            HIF_SDIO_WARN_FUNC("vendor id(0x%x) and device id(0x%x) of sdio_func are not supported in mtk_sdio_id_tbl!\n",
+                pinfo->func_tbl[i].manf_id,
+                pinfo->func_tbl[i].card_id);
+            goto out;
+        }
+    }
+    HIF_SDIO_DBG_FUNC("hif_sdio_check_supported_sdio_id() done!\n");
+
+    //4 <3> check if the specific {manf id, card id, function number} tuple is
+    //4 already resigstered
+    for ( i=0; i<pinfo->func_tbl_size; i++ )
+    {
+        ret = hif_sdio_check_duplicate_sdio_id( pinfo->func_tbl[i].manf_id, pinfo->func_tbl[i].card_id, pinfo->func_tbl[i].func_num );
+        if(ret)
+        {
+            HIF_SDIO_WARN_FUNC("vendor id(0x%x), device id(0x%x), and fun_num(%d) of sdio_func are duplicated in g_hif_sdio_clt_drv_list!\n",
+                pinfo->func_tbl[i].manf_id,
+                pinfo->func_tbl[i].card_id,
+                pinfo->func_tbl[i].func_num );
+            goto out;
+        }
+    }
+    HIF_SDIO_DBG_FUNC("hif_sdio_check_duplicate_sdio_id() done!\n");
+
+    //4 <4> add the specified {manf id, card id, function number} tuple to registered client list
+    HIF_SDIO_DBG_FUNC("pinfo->func_tbl_size:%d\n", pinfo->func_tbl_size);
+    for ( i=0; i<pinfo->func_tbl_size; i++ )
+    {
+        ret = hif_sdio_add_clt_list( &clt_index, pinfo, i );
+        if(ret)
+        {
+            HIF_SDIO_WARN_FUNC("client's info are added in registed client list failed (buffer is full)!\n");
+            goto out;
+        }
+        HIF_SDIO_DBG_FUNC("hif_sdio_add_clt_list() done (gRefCount=%d)!\n", gRefCount);
+
+    //4 <5> if the specific {manf id, card id, function number} tuple has already
+    //4 been probed by mmc, schedule another task to call client's .hif_clt_probe()
+        for ( j=0; j<CFG_CLIENT_COUNT; j++ )
+        {
+            // probed spin lock
+            spin_lock_bh( &g_hif_sdio_lock_info.probed_list_lock );
+            if ( g_hif_sdio_probed_func_list[j].func == 0 )
+            {
+                // probed spin unlock
+                spin_unlock_bh( &g_hif_sdio_lock_info.probed_list_lock );
+                continue;
+            }
+            /* the function has been probed */
+            if ( (g_hif_sdio_clt_drv_list[clt_index].func_info->manf_id == g_hif_sdio_probed_func_list[j].func->vendor) &&\
+                 (g_hif_sdio_clt_drv_list[clt_index].func_info->card_id == g_hif_sdio_probed_func_list[j].func->device) &&\
+                 (g_hif_sdio_clt_drv_list[clt_index].func_info->func_num == g_hif_sdio_probed_func_list[j].func->num) )
+            {
+                g_hif_sdio_probed_func_list[j].clt_idx = clt_index;
+                // probed spin unlock
+                spin_unlock_bh( &g_hif_sdio_lock_info.probed_list_lock );
+
+                /* use worker thread to perform the client's .hif_clt_probe() */
+                clt_probe_worker_info = vmalloc( sizeof(MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO) );
+                INIT_WORK( &clt_probe_worker_info->probe_work, hif_sdio_clt_probe_worker );
+                clt_probe_worker_info->registinfo_p = &g_hif_sdio_clt_drv_list[clt_index];
+                clt_probe_worker_info->probe_idx = j;
+                schedule_work( &clt_probe_worker_info->probe_work );
+
+        //4 <5.1> remember to do claim_irq for the func if it's irq had been released.
+                if ( !(g_hif_sdio_probed_func_list[j].func->irq_handler) )
+                {
+                    sdio_claim_host(g_hif_sdio_probed_func_list[j].func);
+                    ret = sdio_claim_irq(g_hif_sdio_probed_func_list[j].func, hif_sdio_irq);
+                    mtk_wcn_sdio_irq_flag_set (1);
+                    sdio_release_host(g_hif_sdio_probed_func_list[j].func);
+                    HIF_SDIO_INFO_FUNC("sdio_claim_irq for func(0x%p) j(%d) v(0x%x) d(0x%x) ok\n",
+                        g_hif_sdio_probed_func_list[j].func, j,
+                        g_hif_sdio_probed_func_list[j].func->vendor,
+                        g_hif_sdio_probed_func_list[j].func->device
+                        );
+                }
+        //4 <5.2> Reset the block size of the function provided by client
+                HIF_SDIO_INFO_FUNC("Reset sdio block size: %d!\n", g_hif_sdio_clt_drv_list[clt_index].func_info->blk_sz);
+                sdio_claim_host(g_hif_sdio_probed_func_list[j].func);
+                ret = sdio_set_block_size(g_hif_sdio_probed_func_list[j].func,\
+                                        g_hif_sdio_clt_drv_list[clt_index].func_info->blk_sz);
+                sdio_release_host(g_hif_sdio_probed_func_list[j].func);
+            }
+            else
+            {
+                // probed spin unlock
+                spin_unlock_bh( &g_hif_sdio_lock_info.probed_list_lock );
+            }
+        }
+        HIF_SDIO_DBG_FUNC("map g_hif_sdio_clt_drv_list to g_hif_sdio_probed_func_list done!\n");
+    }
+    ret = HIF_SDIO_ERR_SUCCESS;
+    gRefCount++;
+
+out:
+    //4 <last> error handling
+
+    HIF_SDIO_DBG_FUNC("end!\n");
+    return ret;
+} /* end of mtk_wcn_hif_sdio_client_reg() */
+
+/*!
+ * \brief MTK hif sdio client un-registration function
+ *
+ * Client uses this function to un-register itself
+ *
+ * \param pinfo a pointer of client's information
+ *
+ * \retval 0    register successfully
+ * \retval < 0  list error code here
+ */
+INT32 mtk_wcn_hif_sdio_client_unreg (
+    const MTK_WCN_HIF_SDIO_CLTINFO *pinfo
+    )
+{
+    INT32  ret = -HIF_SDIO_ERR_FAIL;
+    INT32  clt_list_index = 0;
+    UINT32 i = 0;
+    UINT32 j = 0;
+
+    HIF_SDIO_INFO_FUNC("start!\n");
+
+    //4 <1> check if input pointer is valid
+    HIF_SDIO_ASSERT( pinfo );
+
+    //4 <2> check if input parameters are all supported and valid
+    for ( i=0; i<pinfo->func_tbl_size; i++ )
+    {
+        ret = hif_sdio_check_supported_sdio_id( pinfo->func_tbl[i].manf_id, pinfo->func_tbl[i].card_id );
+        if(ret)
+        {
+            HIF_SDIO_WARN_FUNC("vendor id(0x%x) and device id(0x%x) of sdio_func are not supported in mtk_sdio_id_tbl!\n",
+                pinfo->func_tbl[i].manf_id,
+                pinfo->func_tbl[i].card_id);
+            goto out;
+        }
+    }
+
+    //4 <3> check if the specific {manf id, card id, function number} tuple is already resigstered
+    //4 and find the corresponding client ctx and call client's .hif_clt_remove() in THIS context
+    for ( i=0; i<pinfo->func_tbl_size; i++ )
+    {
+        clt_list_index = hif_sdio_find_clt_list_index(pinfo->func_tbl[i].manf_id, pinfo->func_tbl[i].card_id, pinfo->func_tbl[i].func_num);
+        if ( clt_list_index < 0 )
+        {
+            HIF_SDIO_WARN_FUNC("vendor id(0x%x), device id(0x%x), and fun_num(%d) client info is not in the client's registed list!\n",
+                pinfo->func_tbl[i].manf_id,
+                pinfo->func_tbl[i].card_id,
+                pinfo->func_tbl[i].func_num );
+            ret = -HIF_SDIO_ERR_FAIL;
+            goto out;
+        }
+
+    //4 <4> mark the specified {manf id, card id, function number} tuple as
+    //4 un-registered and invalidate client's context
+        hif_sdio_init_clt_list( clt_list_index );
+
+        /* un-map g_hif_sdio_clt_drv_list index in g_hif_sdio_probed_func_list */
+        for ( j=0; j<CFG_CLIENT_COUNT; j++ )
+        {
+            if ( g_hif_sdio_probed_func_list[j].clt_idx == clt_list_index )
+            {
+                g_hif_sdio_probed_func_list[j].clt_idx = -1;
+            }
+        }
+    }
+    gRefCount--;
+
+    ret = HIF_SDIO_ERR_SUCCESS;
+out:
+    HIF_SDIO_INFO_FUNC("end (gRefCount=%d) !\n", gRefCount);
+    return ret;
+}/* end of mtk_wcn_hif_sdio_client_unreg() */
+
+/*!
+ * \brief
+ *
+ * detailed descriptions
+ *
+ * \param ctx client's context variable
+ *
+ * \retval 0    register successfully
+ * \retval < 0  list error code here
+ */
+INT32 mtk_wcn_hif_sdio_readb (
+    MTK_WCN_HIF_SDIO_CLTCTX ctx,
+    UINT32 offset,
+    PUINT8 pvb
+    )
+{
+#if HIF_SDIO_UPDATE
+    INT32 ret;
+    struct sdio_func* func;
+#else
+    INT32 ret = -HIF_SDIO_ERR_FAIL;
+    int probe_index = -1;
+    struct sdio_func* func = 0;
+#endif
+
+    HIF_SDIO_DBG_FUNC("start!\n");
+    HIF_SDIO_ASSERT( pvb );
+
+    //4 <1> check if ctx is valid, registered, and probed
+#if HIF_SDIO_UPDATE
+    ret = -HIF_SDIO_ERR_FAIL;
+    func = hif_sdio_ctx_to_func(ctx);
+    if (!func) {
+        ret = -HIF_SDIO_ERR_FAIL;
+        goto out;
+    }
+#else
+    probe_index = CLTCTX_IDX(ctx);
+    if( probe_index < 0 )   /* the function has not been probed */
+    {
+        HIF_SDIO_WARN_FUNC("can't find client in probed list!\n");
+        ret = -HIF_SDIO_ERR_FAIL;
+        goto out;
+    }
+    else
+    {
+        if ( g_hif_sdio_probed_func_list[probe_index].clt_idx < 0 )   /* the client has not been registered */
+        {
+            HIF_SDIO_WARN_FUNC("can't find client in registered list!\n");
+            ret = -HIF_SDIO_ERR_FAIL;
+            goto out;
+        }
+    }
+    func = g_hif_sdio_probed_func_list[probe_index].func;
+#endif
+
+    //4 <2>
+    sdio_claim_host(func);
+    *pvb = sdio_readb(func, offset, &ret);
+    sdio_release_host(func);
+
+    //4 <3> check result code and return proper error code
+
+out:
+    HIF_SDIO_DBG_FUNC("end!\n");
+    return ret;
+} /* end of mtk_wcn_hif_sdio_client_unreg() */
+
+/*!
+ * \brief
+ *
+ * detailed descriptions
+ *
+ * \param ctx client's context variable
+ *
+ * \retval 0    register successfully
+ * \retval < 0  list error code here
+ */
+INT32 mtk_wcn_hif_sdio_writeb (
+    MTK_WCN_HIF_SDIO_CLTCTX ctx,
+    UINT32 offset,
+    UINT8 vb
+    )
+{
+#if HIF_SDIO_UPDATE
+    INT32 ret;
+    struct sdio_func* func;
+#else
+    INT32 ret = -HIF_SDIO_ERR_FAIL;
+    int probe_index = -1;
+    struct sdio_func* func = 0;
+#endif
+
+    HIF_SDIO_DBG_FUNC("start!\n");
+
+    //4 <1> check if ctx is valid, registered, and probed
+#if HIF_SDIO_UPDATE
+    ret = -HIF_SDIO_ERR_FAIL;
+    func = hif_sdio_ctx_to_func(ctx);
+    if (!func) {
+        ret = -HIF_SDIO_ERR_FAIL;
+        goto out;
+    }
+#else
+    probe_index = CLTCTX_IDX(ctx);
+    if( probe_index < 0 )   /* the function has not been probed */
+    {
+        HIF_SDIO_WARN_FUNC("can't find client in probed list!\n");
+        ret = -HIF_SDIO_ERR_FAIL;
+        goto out;
+    }
+    else
+    {
+        if ( g_hif_sdio_probed_func_list[probe_index].clt_idx < 0 )   /* the client has not been registered */
+        {
+            HIF_SDIO_WARN_FUNC("can't find client in registered list!\n");
+            ret = -HIF_SDIO_ERR_FAIL;
+            goto out;
+        }
+    }
+    func = g_hif_sdio_probed_func_list[probe_index].func;
+#endif
+
+    //4 <1.1> check if input parameters are valid
+
+    //4 <2>
+    wmt_tra_sdio_update();
+    sdio_claim_host(func);
+    sdio_writeb(func, vb, offset, &ret);
+    sdio_release_host(func);
+
+    //4 <3> check result code and return proper error code
+
+out:
+    HIF_SDIO_DBG_FUNC("end!\n");
+    return ret;
+} /* end of mtk_wcn_hif_sdio_client_unreg() */
+
+/*!
+ * \brief
+ *
+ * detailed descriptions
+ *
+ * \param ctx client's context variable
+ *
+ * \retval 0    register successfully
+ * \retval < 0  list error code here
+ */
+INT32 mtk_wcn_hif_sdio_readl (
+    MTK_WCN_HIF_SDIO_CLTCTX ctx,
+    UINT32 offset,
+    PUINT32 pvl
+    )
+{
+#if HIF_SDIO_UPDATE
+    INT32 ret;
+    struct sdio_func* func;
+#else
+    INT32 ret = -HIF_SDIO_ERR_FAIL;
+    int probe_index = -1;
+    struct sdio_func* func = 0;
+#endif
+
+    HIF_SDIO_DBG_FUNC("start!\n");
+    HIF_SDIO_ASSERT( pvl );
+
+    //4 <1> check if ctx is valid, registered, and probed
+#if HIF_SDIO_UPDATE
+    ret = -HIF_SDIO_ERR_FAIL;
+    func = hif_sdio_ctx_to_func(ctx);
+    if (!func) {
+        ret = -HIF_SDIO_ERR_FAIL;
+        goto out;
+    }
+#else
+    probe_index = CLTCTX_IDX(ctx);
+    if( probe_index < 0 )   /* the function has not been probed */
+    {
+        HIF_SDIO_WARN_FUNC("can't find client in probed list!\n");
+        ret = -HIF_SDIO_ERR_FAIL;
+        goto out;
+    }
+    else
+    {
+        if ( g_hif_sdio_probed_func_list[probe_index].clt_idx < 0 )   /* the client has not been registered */
+        {
+            HIF_SDIO_WARN_FUNC("can't find client in registered list!\n");
+            ret = -HIF_SDIO_ERR_FAIL;
+            goto out;
+        }
+    }
+    func = g_hif_sdio_probed_func_list[probe_index].func;
+#endif
+    //4 <1.1> check if input parameters are valid
+
+    //4 <2>
+    sdio_claim_host(func);
+    *pvl = sdio_readl(func, offset, &ret);
+    sdio_release_host(func);
+
+    //4 <3> check result code and return proper error code
+
+out:
+    HIF_SDIO_DBG_FUNC("end!\n");
+    return ret;
+} /* end of mtk_wcn_hif_sdio_client_unreg() */
+
+/*!
+ * \brief
+ *
+ * detailed descriptions
+ *
+ * \param ctx client's context variable
+ *
+ * \retval 0    register successfully
+ * \retval < 0  list error code here
+ */
+INT32 mtk_wcn_hif_sdio_writel (
+    MTK_WCN_HIF_SDIO_CLTCTX ctx,
+    UINT32 offset,
+    UINT32 vl
+    )
+{
+#if HIF_SDIO_UPDATE
+    INT32 ret;
+    struct sdio_func* func;
+#else
+    INT32 ret = -HIF_SDIO_ERR_FAIL;
+    int probe_index = -1;
+    struct sdio_func* func = 0;
+#endif
+
+    HIF_SDIO_DBG_FUNC("start!\n");
+
+    //4 <1> check if ctx is valid, registered, and probed
+#if HIF_SDIO_UPDATE
+    ret = -HIF_SDIO_ERR_FAIL;
+    func = hif_sdio_ctx_to_func(ctx);
+    if (!func) {
+        ret = -HIF_SDIO_ERR_FAIL;
+        goto out;
+    }
+#else
+    probe_index = CLTCTX_IDX(ctx);
+    if( probe_index < 0 )   /* the function has not been probed */
+    {
+        HIF_SDIO_WARN_FUNC("can't find client in probed list!\n");
+        ret = -HIF_SDIO_ERR_FAIL;
+        goto out;
+    }
+    else
+    {
+        if ( g_hif_sdio_probed_func_list[probe_index].clt_idx < 0 )   /* the client has not been registered */
+        {
+            HIF_SDIO_WARN_FUNC("can't find client in registered list!\n");
+            ret = -HIF_SDIO_ERR_FAIL;
+            goto out;
+        }
+    }
+    func = g_hif_sdio_probed_func_list[probe_index].func;
+#endif
+    //4 <1.1> check if input parameters are valid
+
+    //4 <2>
+    wmt_tra_sdio_update();
+    sdio_claim_host(func);
+    sdio_writel(func, vl, offset, &ret);
+    sdio_release_host(func);
+
+    //4 <3> check result code and return proper error code
+
+out:
+    HIF_SDIO_DBG_FUNC("end!\n");
+    return ret;
+} /* end of mtk_wcn_hif_sdio_client_unreg() */
+
+/*!
+ * \brief
+ *
+ * detailed descriptions
+ *
+ * \param ctx client's context variable
+ *
+ * \retval 0    register successfully
+ * \retval < 0  list error code here
+ */
+INT32 mtk_wcn_hif_sdio_read_buf (
+    MTK_WCN_HIF_SDIO_CLTCTX ctx,
+    UINT32 offset,
+    PUINT32 pbuf,
+    UINT32 len
+    )
+{
+#if HIF_SDIO_UPDATE
+    INT32 ret;
+    struct sdio_func* func;
+#else
+    INT32 ret = -HIF_SDIO_ERR_FAIL;
+    int probe_index = -1;
+    struct sdio_func* func = 0;
+#endif
+
+    HIF_SDIO_DBG_FUNC("start!\n");
+    HIF_SDIO_ASSERT( pbuf );
+
+    //4 <1> check if ctx is valid, registered, and probed
+#if HIF_SDIO_UPDATE
+    ret = -HIF_SDIO_ERR_FAIL;
+    func = hif_sdio_ctx_to_func(ctx);
+    if (!func) {
+        ret = -HIF_SDIO_ERR_FAIL;
+        goto out;
+    }
+#else
+    probe_index = CLTCTX_IDX(ctx);
+    if( probe_index < 0 )   /* the function has not been probed */
+    {
+        HIF_SDIO_WARN_FUNC("can't find client in probed list!\n");
+        ret = -HIF_SDIO_ERR_FAIL;
+        goto out;
+    }
+    else
+    {
+        if ( g_hif_sdio_probed_func_list[probe_index].clt_idx < 0 )   /* the client has not been registered */
+        {
+            HIF_SDIO_WARN_FUNC("can't find client in registered list!\n");
+            ret = -HIF_SDIO_ERR_FAIL;
+            goto out;
+        }
+    }
+    func = g_hif_sdio_probed_func_list[probe_index].func;
+#endif
+    //4 <1.1> check if input parameters are valid
+
+    //4 <2>
+    sdio_claim_host(func);
+    ret = sdio_readsb(func, pbuf, offset, len);
+    sdio_release_host(func);
+
+    //4 <3> check result code and return proper error code
+
+out:
+    HIF_SDIO_DBG_FUNC("end!\n");
+    return ret;
+} /* end of mtk_wcn_hif_sdio_read_buf() */
+
+
+/*!
+ * \brief
+ *
+ * detailed descriptions
+ *
+ * \param ctx client's context variable
+ *
+ * \retval 0    register successfully
+ * \retval < 0  list error code here
+ */
+INT32 mtk_wcn_hif_sdio_write_buf (
+    MTK_WCN_HIF_SDIO_CLTCTX ctx,
+    UINT32 offset,
+    PUINT32 pbuf,
+    UINT32 len
+    )
+{
+#if HIF_SDIO_UPDATE
+    INT32 ret;
+    struct sdio_func* func;
+#else
+    INT32 ret = -HIF_SDIO_ERR_FAIL;
+    int probe_index = -1;
+    struct sdio_func* func = 0;
+#endif
+
+    HIF_SDIO_DBG_FUNC("start!\n");
+    HIF_SDIO_ASSERT( pbuf );
+
+    //4 <1> check if ctx is valid, registered, and probed
+#if HIF_SDIO_UPDATE
+    ret = -HIF_SDIO_ERR_FAIL;
+    func = hif_sdio_ctx_to_func(ctx);
+    if (!func) {
+        ret = -HIF_SDIO_ERR_FAIL;
+        goto out;
+    }
+#else
+    probe_index = CLTCTX_IDX(ctx);
+    if( probe_index < 0 )   /* the function has not been probed */
+    {
+        HIF_SDIO_WARN_FUNC("can't find client in probed list!\n");
+        ret = -HIF_SDIO_ERR_FAIL;
+        goto out;
+    }
+    else
+    {
+        if ( g_hif_sdio_probed_func_list[probe_index].clt_idx < 0 )   /* the client has not been registered */
+        {
+            HIF_SDIO_WARN_FUNC("can't find client in registered list!\n");
+            ret = -HIF_SDIO_ERR_FAIL;
+            goto out;
+        }
+    }
+    func = g_hif_sdio_probed_func_list[probe_index].func;
+#endif
+    //4 <1.1> check if input parameters are valid
+
+    //4 <2>
+    wmt_tra_sdio_update();
+    sdio_claim_host(func);
+    ret = sdio_writesb(func, offset, pbuf, len);
+    sdio_release_host(func);
+
+    //4 <3> check result code and return proper error code
+
+out:
+    HIF_SDIO_DBG_FUNC("ret(%d) end!\n", ret);
+
+    return ret;
+} /* end of mtk_wcn_hif_sdio_write_buf() */
+
+/*!
+ * \brief store client driver's private data function.
+ *
+ *
+ * \param clent's MTK_WCN_HIF_SDIO_CLTCTX.
+ *
+ * \retval none.
+ */
+void mtk_wcn_hif_sdio_set_drvdata(
+    MTK_WCN_HIF_SDIO_CLTCTX ctx,
+    void* private_data_p
+    )
+{
+    UINT8 probed_idx = CLTCTX_IDX(ctx);
+
+    if (unlikely(!CLTCTX_IDX_VALID(probed_idx))) {   /* invalid index in CLTCTX */
+        HIF_SDIO_WARN_FUNC("invalid idx in ctx(0x%x), private_data_p not stored!\n", ctx);
+    }
+    else {
+        /* store client driver's private data to dev driver */
+        g_hif_sdio_probed_func_list[probed_idx].private_data_p = private_data_p;
+        HIF_SDIO_DBG_FUNC("private_data_p(0x%p) for ctx(0x%x) probed idx(%d) stored!\n",
+            private_data_p, ctx, probed_idx);
+    }
+}
+
+/*!
+ * \brief get client driver's private data function.
+ *
+ *
+ * \param clent's MTK_WCN_HIF_SDIO_CLTCTX.
+ *
+ * \retval private data pointer.
+ */
+void* mtk_wcn_hif_sdio_get_drvdata(
+    MTK_WCN_HIF_SDIO_CLTCTX ctx
+    )
+{
+    UINT8 probed_idx = CLTCTX_IDX(ctx);
+
+    /* get client driver's private data to dev driver */
+    if (likely(CLTCTX_IDX_VALID(probed_idx)))
+    {
+        return g_hif_sdio_probed_func_list[probed_idx].private_data_p;
+    }
+    else
+    {
+        /* invalid index in CLTCTX */
+        HIF_SDIO_WARN_FUNC("invalid idx in ctx(0x%x), return null!\n", ctx);
+        return NULL;
+    }
+}
+
+/*!
+ * \brief control stp/wifi on/off from wmt.
+ *
+ *
+ * \param (1)control function type, (2)on/off control.
+ *
+ * \retval (1)control results ,(2)unknow type: -5.
+ * \retval 0:success, -11:not probed, -12:already on, -13:not registered, other errors.
+ */
+INT32
+mtk_wcn_hif_sdio_wmt_control (
+    WMT_SDIO_FUNC_TYPE func_type,
+    MTK_WCN_BOOL is_on
+    )
+{
+    // TODO:[FixMe][George]: return value of this function shall distinguish
+    // 1) not probed by mmc_core yet or
+    // 2) probed by mmc_core but init fail...
+    switch (func_type) {
+    case WMT_SDIO_FUNC_STP:
+        if (is_on == MTK_WCN_BOOL_TRUE) {
+            return hif_sdio_stp_on();
+        }
+        else {
+            return hif_sdio_stp_off();
+        }
+        break;
+
+    case WMT_SDIO_FUNC_WIFI:
+        if (is_on == MTK_WCN_BOOL_TRUE) {
+            return hif_sdio_wifi_on();
+        }
+        else {
+            return hif_sdio_wifi_off();
+        }
+        break;
+
+    default:
+        HIF_SDIO_WARN_FUNC("unknown type(%d)\n", func_type);
+        return HIF_SDIO_ERR_INVALID_PARAM;
+    }
+}
+
+/*!
+ * \brief ???
+ *
+ * \detail ???
+ *
+ * \param ctx a context provided by client driver
+ * \param struct device ** ???
+ *
+ * \retval none
+ */
+void mtk_wcn_hif_sdio_get_dev(
+    MTK_WCN_HIF_SDIO_CLTCTX ctx,
+    struct device **dev
+    )
+{
+#if HIF_SDIO_UPDATE
+    struct sdio_func* func;
+#else
+    UINT8 probe_index = CLTCTX_IDX(ctx);
+#endif
+
+#if HIF_SDIO_UPDATE
+    *dev = NULL; //ensure we does not return any invalid value back.
+    func = hif_sdio_ctx_to_func(ctx);
+    if (unlikely(!func)) {
+        HIF_SDIO_WARN_FUNC("no valid *func with ctx(0x%x)\n", ctx);
+        return;
+    }
+    else {
+        *dev = &(func->dev);
+        HIF_SDIO_DBG_FUNC("return *dev(0x%p) for ctx(0x%x)\n", *dev, ctx);
+    }
+#else
+    if (probe_index < 0) {
+        HIF_SDIO_WARN_FUNC("func not probed, probe_index = %d", probe_index);
+        return;
+    }
+    else{
+        *dev = &g_hif_sdio_probed_func_list[probe_index].func->dev;
+    }
+#endif
+}
+
+/*!
+ * \brief client's probe() function.
+ *
+ *
+ * \param work queue structure.
+ *
+ * \retval none.
+ */
+static int hif_sdio_clt_probe_func (
+    MTK_WCN_HIF_SDIO_REGISTINFO *registinfo_p,
+    INT8 probe_idx
+    )
+{
+    UINT16 card_id = 0;
+    UINT16 func_num = 0;
+    UINT16 blk_sz = 0;
+    int ret;
+
+    HIF_SDIO_DBG_FUNC("start!\n");
+    HIF_SDIO_ASSERT( registinfo_p );
+    if (!registinfo_p) {
+        HIF_SDIO_WARN_FUNC("registinfo_p NULL!!!\n");
+        return -1;
+    }
+
+    /* special case handling: if the clt's unregister is called during probe procedures */
+    if ( !registinfo_p->func_info || !registinfo_p->sdio_cltinfo) {
+        HIF_SDIO_WARN_FUNC("client's registinfo_p is cleared !!!\n");
+        return -1;
+    }
+
+    card_id = registinfo_p->func_info->card_id;
+    func_num = registinfo_p->func_info->func_num;
+    blk_sz = registinfo_p->func_info->blk_sz;
+    ret = registinfo_p->sdio_cltinfo->hif_clt_probe( CLTCTX(card_id, func_num, blk_sz, probe_idx),\
+                                                            registinfo_p->func_info );
+
+    HIF_SDIO_INFO_FUNC("clt_probe_func card_id(%x) func_num(%x) blk_sz(%d) prob_idx(%x) ret(%d) %s\n",
+        card_id, func_num, blk_sz, probe_idx, ret, (ret) ? "fail" : "ok");
+
+    return ret;
+}
+
+/*!
+ * \brief client's probe() worker.
+ *
+ *
+ * \param work queue structure.
+ *
+ * \retval none.
+ */
+static void hif_sdio_clt_probe_worker(
+    struct work_struct *work
+    )
+{
+    MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO *clt_worker_info_p = 0;
+    UINT16 card_id = 0;
+    UINT16 func_num = 0;
+    UINT16 blk_sz = 0;
+    INT8   prob_idx = 0;
+
+    HIF_SDIO_DBG_FUNC("start!\n");
+
+    HIF_SDIO_ASSERT( work );
+
+    /* get client's information */
+    clt_worker_info_p = container_of( work, MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO, probe_work );
+    HIF_SDIO_ASSERT( clt_worker_info_p );
+    HIF_SDIO_ASSERT( clt_worker_info_p->registinfo_p );
+
+    /* special case handling: if the clt's unregister is called during probe procedures */
+    if ( (clt_worker_info_p->registinfo_p->func_info == 0) || (clt_worker_info_p->registinfo_p->sdio_cltinfo==0) )
+    {
+        HIF_SDIO_WARN_FUNC("client's registinfo_p is cleared !!!\n");
+        vfree( clt_worker_info_p );
+        return;
+    }
+
+    card_id = clt_worker_info_p->registinfo_p->func_info->card_id;
+    func_num = clt_worker_info_p->registinfo_p->func_info->func_num;
+    blk_sz = clt_worker_info_p->registinfo_p->func_info->blk_sz;
+    prob_idx = clt_worker_info_p->probe_idx;
+
+    /* Execute client's probe() func */
+    clt_worker_info_p->registinfo_p->sdio_cltinfo->hif_clt_probe( CLTCTX(card_id, func_num, blk_sz, prob_idx),\
+                                                        clt_worker_info_p->registinfo_p->func_info );
+
+    vfree( clt_worker_info_p );
+
+    HIF_SDIO_DBG_FUNC("card_id(0x%x) func_num(0x%x) blk_sz(0x%x) prob_idx(0x%x)\n", card_id, func_num, blk_sz, prob_idx);
+    HIF_SDIO_DBG_FUNC("end!\n");
+}
+
+/*!
+ * \brief client's probe() worker.
+ *
+ *
+ * \param work queue structure.
+ *
+ * \retval none.
+ */
+static void
+hif_sdio_dump_probe_list (void)
+{
+    int i;
+
+    HIF_SDIO_DBG_FUNC("== DUMP probed list start ==\n");
+
+    for (i = 0; i < CFG_CLIENT_COUNT; i++) {
+        if (g_hif_sdio_probed_func_list[i].func) {
+            HIF_SDIO_DBG_FUNC("index(%d) func(0x%p) clt_idx(%d)\n",
+                i, g_hif_sdio_probed_func_list[i].func,
+                g_hif_sdio_probed_func_list[i].clt_idx);
+
+            HIF_SDIO_DBG_FUNC("vendor(0x%x) device(0x%x) num(0x%x) state(%d)\n",
+                g_hif_sdio_probed_func_list[i].func->vendor,
+                g_hif_sdio_probed_func_list[i].func->device,
+                g_hif_sdio_probed_func_list[i].func->num,
+                g_hif_sdio_probed_func_list[i].on_by_wmt);
+
+        }
+    }
+
+    HIF_SDIO_DBG_FUNC("== DUMP probed list end ==\n");
+}
+
+
+/*!
+ * \brief Initialize g_hif_sdio_probed_func_list
+ *
+ *
+ * \param index of g_hif_sdio_probed_func_list.
+ *
+ * \retval none.
+ */
+static void hif_sdio_init_probed_list(
+    INT32 index
+    )
+{
+    if ( (index >= 0) && (index < CFG_CLIENT_COUNT) )
+    {
+        /* probed spin lock */
+        spin_lock_bh( &g_hif_sdio_lock_info.probed_list_lock );
+        g_hif_sdio_probed_func_list[index].func = 0;
+        g_hif_sdio_probed_func_list[index].clt_idx = -1;
+        g_hif_sdio_probed_func_list[index].private_data_p = 0;
+        g_hif_sdio_probed_func_list[index].on_by_wmt = MTK_WCN_BOOL_FALSE;
+        /* probed spin unlock */
+        spin_unlock_bh( &g_hif_sdio_lock_info.probed_list_lock );
+    }
+    else
+    {
+        HIF_SDIO_ERR_FUNC("index is out of g_hif_sdio_probed_func_list[] boundary!\n");
+    }
+}
+
+
+/*!
+ * \brief Initialize g_hif_sdio_clt_drv_list
+ *
+ *
+ * \param index of g_hif_sdio_clt_drv_list.
+ *
+ * \retval none.
+ */
+static void hif_sdio_init_clt_list(
+    INT32 index
+    )
+{
+    // client list spin lock
+    spin_lock_bh( &g_hif_sdio_lock_info.clt_list_lock );
+    if ( (index >= 0) && (index < CFG_CLIENT_COUNT) )
+    {
+        g_hif_sdio_clt_drv_list[index].sdio_cltinfo = 0;
+        g_hif_sdio_clt_drv_list[index].func_info = 0;
+    }
+    else
+    {
+        HIF_SDIO_ERR_FUNC("index is out of g_hif_sdio_clt_drv_list[] boundary!\n");
+    }
+    // client list spin unlock
+    spin_unlock_bh( &g_hif_sdio_lock_info.clt_list_lock );
+}
+
+
+/*!
+ * \brief find matched g_hif_sdio_probed_func_list index from sdio function handler
+ *
+ *
+ * \param sdio function handler
+ *
+ * \retval -1    index not found
+ * \retval >= 0  return found index
+ */
+static int hif_sdio_find_probed_list_index_by_func(
+    struct sdio_func* func
+    )
+{
+    int i = 0;
+
+    HIF_SDIO_ASSERT( func );
+
+    for( i=0; i<CFG_CLIENT_COUNT; i++ )
+    {
+        if ( g_hif_sdio_probed_func_list[i].func == func )
+        {
+            return i;
+        }
+    }
+
+    return -1;
+}
+
+/*!
+ * \brief find matched g_hif_sdio_probed_func_list from vendor_id, device_id, and function number
+ *
+ *
+ * \param vendor id, device id, and function number of the sdio card.
+ *
+ * \retval -1    index not found
+ * \retval >= 0  return found index
+ */
+static int hif_sdio_find_probed_list_index_by_id_func(
+    UINT16 vendor,
+    UINT16 device,
+    UINT16 func_num
+    )
+{
+    int i;
+    for (i = 0; i < CFG_CLIENT_COUNT; i++) {
+        if (g_hif_sdio_probed_func_list[i].func) {
+            HIF_SDIO_DBG_FUNC("probed entry: vendor(0x%x) device(0x%x) num(0x%x)\n",
+                g_hif_sdio_probed_func_list[i].func->vendor,
+                g_hif_sdio_probed_func_list[i].func->device,
+                g_hif_sdio_probed_func_list[i].func->num);
+        }
+    }
+    for (i = 0; i < CFG_CLIENT_COUNT; i++) {
+        if (!g_hif_sdio_probed_func_list[i].func) {
+            continue;
+        }
+        else if ( (g_hif_sdio_probed_func_list[i].func->vendor == vendor) &&
+            (g_hif_sdio_probed_func_list[i].func->device == device) &&
+            (g_hif_sdio_probed_func_list[i].func->num == func_num)  )
+        {
+            return i;
+        }
+    }
+
+    if (i == CFG_CLIENT_COUNT ) {
+        /*
+        printk(KERN_INFO DRV_NAME "Cannot find vendor:0x%x, device:0x%x, func_num:0x%x, i=%d\n",
+            vendor, device, func_num, i);
+        */
+        /* client func has not been probed */
+        return -1;
+    }
+    return -1;
+}
+
+/*!
+ * \brief find matched g_hif_sdio_clt_drv_list index
+ *
+ * find the matched g_hif_sdio_clt_drv_list index from card_id and function number.
+ *
+ * \param vendor id, device id, and function number of the sdio card
+ *
+ * \retval -1    index not found
+ * \retval >= 0  return found index
+ */
+static int hif_sdio_find_clt_list_index (
+    UINT16 vendor,
+    UINT16 device,
+    UINT16 func_num
+    )
+{
+    int i = 0;
+
+    for( i=0; i<CFG_CLIENT_COUNT; i++ )
+    {
+        if ( g_hif_sdio_clt_drv_list[i].func_info != 0 )
+        {
+            if ( (g_hif_sdio_clt_drv_list[i].func_info->manf_id == vendor ) &&\
+                (g_hif_sdio_clt_drv_list[i].func_info->card_id == device ) &&\
+                (g_hif_sdio_clt_drv_list[i].func_info->func_num == func_num ) )
+            {
+                return i;
+            }
+        }
+    }
+
+    return -1;
+}
+
+
+/*!
+ * \brief check if the vendor, device ids are supported in mtk_sdio_id_tbl.
+ *
+ *
+ * \param vendor id and device id of the sdio card
+ *
+ * \retval (-HIF_SDIO_ERR_FAIL)  vendor, device ids are not suppported
+ * \retval HIF_SDIO_ERR_SUCCESS  vendor, device ids are suppported
+ */
+static int hif_sdio_check_supported_sdio_id(
+    UINT16 vendor,
+    UINT16 device
+    )
+{
+    int i = 0;
+
+    for ( i=0; i<CFG_CLIENT_COUNT; i++ )
+    {
+        if ( (mtk_sdio_id_tbl[i].vendor == vendor) && (mtk_sdio_id_tbl[i].device == device) )
+        {
+            return HIF_SDIO_ERR_SUCCESS;  /* mtk_sdio_id is supported */
+        }
+    }
+    return (-HIF_SDIO_ERR_FAIL);    /* mtk_sdio_id is not supported */
+}
+
+
+/*!
+ * \brief check if the vendor, device ids are duplicated in g_hif_sdio_clt_drv_list.
+ *
+ *
+ * \param vendor id, device id, and function number of the sdio card
+ *
+ * \retval (-HIF_SDIO_ERR_DUPLICATED)  vendor, device, func_num are duplicated
+ * \retval HIF_SDIO_ERR_SUCCESS        vendor, device, func_num are not duplicated
+ */
+static int hif_sdio_check_duplicate_sdio_id(
+    UINT16 vendor,
+    UINT16 device,
+    UINT16 func_num
+    )
+{
+    int i = 0;
+
+    for ( i=0; i<CFG_CLIENT_COUNT; i++ )
+    {
+        if( g_hif_sdio_clt_drv_list[i].func_info != 0 )
+        {
+            if ( ( g_hif_sdio_clt_drv_list[i].func_info->manf_id == vendor ) &&\
+                ( g_hif_sdio_clt_drv_list[i].func_info->card_id == device ) &&\
+                ( g_hif_sdio_clt_drv_list[i].func_info->func_num == func_num ) )
+            {
+                return (-HIF_SDIO_ERR_DUPLICATED);  /* duplicated */
+            }
+        }
+    }
+    return HIF_SDIO_ERR_SUCCESS;    /* Not duplicated */
+}
+
+
+/*!
+ * \brief Add the client info into g_hif_sdio_clt_drv_list.
+ *
+ *
+ * \param [output] client's index pointer.
+ * \param MTK_WCN_HIF_SDIO_CLTINFO of client's contex.
+ *
+ * \retval (-HIF_SDIO_ERR_FAIL)  Add to clt_list successfully
+ * \retval HIF_SDIO_ERR_SUCCESS  Add to clt_list failed (buffer is full)
+ */
+static int hif_sdio_add_clt_list(
+    INT32*  clt_index_p,
+    const MTK_WCN_HIF_SDIO_CLTINFO *pinfo,
+    UINT32 tbl_index
+    )
+{
+    int i = 0;
+
+    HIF_SDIO_ASSERT( clt_index_p );
+    HIF_SDIO_ASSERT( pinfo );
+
+    for( i=0; i<CFG_CLIENT_COUNT; i++ )
+    {
+        // client list spin lock
+        spin_lock_bh( &g_hif_sdio_lock_info.clt_list_lock );
+        if( g_hif_sdio_clt_drv_list[i].func_info == 0 )
+        {
+            g_hif_sdio_clt_drv_list[i].func_info = &(pinfo->func_tbl[tbl_index]);
+            g_hif_sdio_clt_drv_list[i].sdio_cltinfo = pinfo;
+            // client list spin unlock
+            spin_unlock_bh( &g_hif_sdio_lock_info.clt_list_lock );
+            *clt_index_p = i;
+            return HIF_SDIO_ERR_SUCCESS;    /* Add to client list successfully */
+        }
+        // client list spin unlock
+        spin_unlock_bh( &g_hif_sdio_lock_info.clt_list_lock );
+    }
+    return (-HIF_SDIO_ERR_FAIL);    /* Add to client list failed (buffer is full) */
+}
+
+#if HIF_SDIO_SUPPORT_SUSPEND
+static int hif_sdio_suspend (struct device *dev)
+{
+    struct sdio_func* func;
+    mmc_pm_flag_t flag;
+    int ret;
+
+    if (!dev) {
+        return -EINVAL;
+    }
+
+    func = dev_to_sdio_func(dev);
+    HIF_SDIO_DBG_FUNC("prepare for func(0x%p)\n", func);
+
+    flag = sdio_get_host_pm_caps(func);
+    if (!(flag & MMC_PM_KEEP_POWER) || !(flag & MMC_PM_WAKE_SDIO_IRQ)) {
+        HIF_SDIO_WARN_FUNC("neither MMC_PM_KEEP_POWER nor MMC_PM_WAKE_SDIO_IRQ is supported by host, return -ENOTSUPP\n");
+        return -ENOTSUPP;
+    }
+
+    /* set both */
+    flag = MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ;
+    ret = sdio_set_host_pm_flags(func, flag);
+    if (ret) {
+        HIF_SDIO_INFO_FUNC("set MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ to host fail(%d)\n", ret);
+        return -EFAULT;
+    }
+    sdio_claim_host(func);
+    HIF_SDIO_INFO_FUNC("set MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ ok\n");
+    return 0;
+}
+
+static int hif_sdio_resume (struct device *dev)
+{
+    struct sdio_func* func;
+
+    if (!dev) {
+        HIF_SDIO_WARN_FUNC("null dev!\n");
+        return -EINVAL;
+    }
+    func = dev_to_sdio_func(dev);
+       sdio_release_host(func);
+    HIF_SDIO_DBG_FUNC("do nothing for func(0x%p)\n", func);
+
+    return 0;
+}
+#endif
+
+/*!
+ * \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 hif_sdio_probe (
+    struct sdio_func *func,
+    const struct sdio_device_id *id
+    )
+{
+    int ret = 0;
+    int i = 0;
+    MTK_WCN_HIF_SDIO_PROBEINFO* hif_sdio_probed_funcp = 0;
+    INT32 probe_index = -1;
+#if 0
+    INT32 clt_index = -1;
+    MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO *clt_probe_worker_info = 0;
+#endif
+
+    HIF_SDIO_INFO_FUNC("start!\n");
+    HIF_SDIO_ASSERT( func );
+    hif_sdio_match_chipid_by_dev_id(id);
+    //4 <0> display debug information
+    HIF_SDIO_INFO_FUNC("vendor(0x%x) device(0x%x) num(0x%x)\n", func->vendor, func->device, func->num);
+    for (i = 0;i < func->card->num_info;i++) {
+        HIF_SDIO_INFO_FUNC("card->info[%d]: %s\n", i, func->card->info[i]);
+    }
+
+    //4 <1> Check if this  is supported by us (mtk_sdio_id_tbl)
+    ret = hif_sdio_check_supported_sdio_id( func->vendor, func->device );
+    if (ret) {
+        HIF_SDIO_WARN_FUNC("vendor id and device id of sdio_func are not supported in mtk_sdio_id_tbl!\n");
+        goto out;
+    }
+
+    //4 <2> Add this struct sdio_func *func to g_hif_sdio_probed_func_list
+    for( i=0; i<CFG_CLIENT_COUNT; i++ )
+    {
+        /* probed spin lock */
+        spin_lock_bh( &g_hif_sdio_lock_info.probed_list_lock );
+        if ( g_hif_sdio_probed_func_list[i].func == 0 )
+        {
+            hif_sdio_probed_funcp = &g_hif_sdio_probed_func_list[i];
+            hif_sdio_probed_funcp->func = func;
+            hif_sdio_probed_funcp->clt_idx = hif_sdio_find_clt_list_index(func->vendor, func->device, func->num);
+            hif_sdio_probed_funcp->on_by_wmt = MTK_WCN_BOOL_FALSE;
+                       hif_sdio_probed_funcp->sdio_irq_enabled = MTK_WCN_BOOL_FALSE;
+            /* probed spin unlock */
+            spin_unlock_bh( &g_hif_sdio_lock_info.probed_list_lock );
+            probe_index = i;
+            break;
+        }
+        else
+        {
+            /* probed spin unlock */
+            spin_unlock_bh( &g_hif_sdio_lock_info.probed_list_lock );
+        }
+    }
+    if ( (probe_index < 0) || (probe_index >= CFG_CLIENT_COUNT) )
+    {
+        HIF_SDIO_ERR_FUNC("probe function list if full!\n");
+        goto out;
+    }
+
+    //4 <3> Initialize this function
+    if ( g_hif_sdio_probed_func_list[probe_index].clt_idx < 0 )
+    {
+        for( i=0; i<CFG_CLIENT_COUNT; i++ )
+        {
+            // client list spin lock
+            spin_lock_bh( &g_hif_sdio_lock_info.clt_list_lock );
+            if ( g_hif_sdio_clt_drv_list[i].func_info == 0 )
+            {
+                // client list spin unlock
+                spin_unlock_bh( &g_hif_sdio_lock_info.clt_list_lock );
+                continue;
+            }
+            HIF_SDIO_INFO_FUNC("manf_id:%x, card_id:%x, func_num:%d\n", g_hif_sdio_clt_drv_list[i].func_info->manf_id, g_hif_sdio_clt_drv_list[i].func_info->card_id, g_hif_sdio_clt_drv_list[i].func_info->func_num );
+            if ( (g_hif_sdio_clt_drv_list[i].func_info->manf_id == g_hif_sdio_probed_func_list[probe_index].func->vendor)&&\
+                 (g_hif_sdio_clt_drv_list[i].func_info->card_id == g_hif_sdio_probed_func_list[probe_index].func->device)&&\
+                 (g_hif_sdio_clt_drv_list[i].func_info->func_num == g_hif_sdio_probed_func_list[probe_index].func->num) )
+            {
+                g_hif_sdio_probed_func_list[probe_index].clt_idx = i;
+                // client list spin unlock
+                spin_unlock_bh( &g_hif_sdio_lock_info.clt_list_lock );
+                break;
+            }
+            else
+            {
+                // client list spin unlock
+                spin_unlock_bh( &g_hif_sdio_lock_info.clt_list_lock );
+            }
+        }
+        HIF_SDIO_INFO_FUNC("map to g_hif_sdio_clt_drv_list[] done: %d\n", g_hif_sdio_probed_func_list[probe_index].clt_idx );
+    }
+
+    //4 <3.1> enable this function
+    sdio_claim_host(func);
+    ret = sdio_enable_func(func);
+    sdio_release_host(func);
+    if (ret) {
+        HIF_SDIO_ERR_FUNC("sdio_enable_func failed!\n");
+        goto out;
+    }
+
+    //4 <3.2> set block size according to the table storing function characteristics
+    if ( hif_sdio_probed_funcp == 0 )
+    {
+        HIF_SDIO_ERR_FUNC("hif_sdio_probed_funcp is null!\n");
+        goto out;
+    }
+    if ( hif_sdio_probed_funcp->clt_idx >= 0 )   /* The clt contex has been registed */
+    {
+        sdio_claim_host(func);
+        ret = sdio_set_block_size(func, g_hif_sdio_clt_drv_list[hif_sdio_probed_funcp->clt_idx].func_info->blk_sz);
+        sdio_release_host(func);
+    }
+    else    /* The clt contex has not been registed */
+    {
+        sdio_claim_host(func);
+        ret = sdio_set_block_size(func, HIF_DEFAULT_BLK_SIZE);
+        sdio_release_host(func);
+    }
+    if (ret) {
+        HIF_SDIO_ERR_FUNC("set sdio block size failed!\n");
+        goto out;
+    }
+
+    HIF_SDIO_INFO_FUNC("cur_blksize(%d) max(%d), host max blk_size(%d) blk_count(%d)\n",
+        func->cur_blksize, func->max_blksize,
+        func->card->host->max_blk_size, func->card->host->max_blk_count
+        );
+
+    // TODO:[ChangeFeature][George]: explain why this block is marked
+#if 0
+    //4 <3.3> claim irq for this function
+    sdio_claim_host(func);
+    ret = sdio_claim_irq(func, hif_sdio_irq);
+    sdio_release_host(func);
+    printk(KERN_INFO "sdio_claim_irq ret=%d\n", ret);
+
+    //4 <3.4> If this struct sdio_func *func is supported by any driver in
+    //4 g_hif_sdio_clt_drv_list, schedule another task to call client's .hif_clt_probe()
+    if ( (clt_index = g_hif_sdio_probed_func_list[probe_index].clt_idx) >= 0 )    /* the function has been registered */
+    {
+        /* use worker thread to perform the client's .hif_clt_probe() */
+        clt_probe_worker_info = vmalloc( sizeof(MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO) );
+        INIT_WORK( &clt_probe_worker_info->probe_work, hif_sdio_clt_probe_worker );
+        clt_probe_worker_info->registinfo_p = &g_hif_sdio_clt_drv_list[clt_index];
+        clt_probe_worker_info->probe_idx = probe_index;
+        schedule_work( &clt_probe_worker_info->probe_work );
+    }
+#endif
+
+    hif_sdio_dump_probe_list();
+
+out:
+    //4 <last> error handling
+    return ret;
+}
+
+
+/*!
+ * \brief hif_sdio remove function
+ *
+ * hif_sdio probe function called by mmc driver when the probed func should be
+ * removed.
+ *
+ * \param func
+ *
+ */
+static void hif_sdio_remove (
+    struct sdio_func *func
+    )
+{
+    int probed_list_index = 0;
+#if 0
+    int registed_list_index = 0;
+#endif
+
+    HIF_SDIO_INFO_FUNC("start!\n");
+    HIF_SDIO_ASSERT( func );
+
+    //4 <1> check input parameter is valid and has been probed previously
+    if (func == NULL) {
+        HIF_SDIO_ERR_FUNC("func null(%p)\n", func);
+        return;
+    }
+
+    //4 <2> if this function has been initialized by any client driver,
+    //4 call client's .hif_clt_remove() call back in THIS context.
+    probed_list_index = hif_sdio_find_probed_list_index_by_func( func );
+    if ( probed_list_index < 0 )
+    {
+        HIF_SDIO_WARN_FUNC("sdio function pointer is not in g_hif_sdio_probed_func_list!\n");
+        return;
+    }
+#if 0
+    registed_list_index = g_hif_sdio_probed_func_list[probed_list_index].clt_idx;
+    if ( registed_list_index >= 0 )
+    {
+        g_hif_sdio_clt_drv_list[registed_list_index].sdio_cltinfo->hif_clt_remove( CLTCTX(func->device, func->num,\
+                                                                            func->cur_blksize, probed_list_index) );
+    }
+#endif
+
+    //4 <3> mark this function as de-initialized and invalidate client's context
+    hif_sdio_init_probed_list(probed_list_index);
+
+#if 0
+    //4 <4> release irq for this function
+    sdio_claim_host(func);
+    sdio_release_irq(func);
+    sdio_release_host(func);
+#endif
+
+    //4 <5> disable this function
+    sdio_claim_host(func);
+    sdio_disable_func(func);
+    sdio_release_host(func);
+
+    //4 <6> mark this function as removed
+
+    HIF_SDIO_INFO_FUNC("sdio func(0x%p) is removed successfully!\n", func);
+}
+
+/*!
+ * \brief hif_sdio interrupt handler
+ *
+ * detailed descriptions
+ *
+ * \param ctx client's context variable
+ *
+ */
+static void hif_sdio_irq (
+    struct sdio_func *func
+    )
+{
+    int probed_list_index = -1;
+    int registed_list_index = -1;
+
+    HIF_SDIO_DBG_FUNC("start!\n");
+
+    //4 <1> check if func is valid
+    HIF_SDIO_ASSERT( func );
+
+    //4 <2> if func has valid corresponding hif_sdio client's context, mark it
+    //4 host-locked, use it to call client's .hif_clt_irq() callback function in
+    //4 THIS context.
+    probed_list_index = hif_sdio_find_probed_list_index_by_func( func );
+    if ( (probed_list_index < 0) || (probed_list_index >= CFG_CLIENT_COUNT) )
+    {
+        HIF_SDIO_ERR_FUNC("probed_list_index not found!\n");
+        return;
+    }
+    /* [George] added for sdio irq sync and mmc single_irq workaround. It's set
+     * enabled later by client driver call mtk_wcn_hif_sdio_enable_irq()
+     */
+    /* skip smp_rmb() here */
+    if (MTK_WCN_BOOL_FALSE == g_hif_sdio_probed_func_list[probed_list_index].sdio_irq_enabled) {
+        HIF_SDIO_WARN_FUNC("func(0x%p),probed_idx(%d) sdio irq not enabled yet\n",
+            func, probed_list_index);
+        return;
+    }
+
+    registed_list_index = g_hif_sdio_probed_func_list[probed_list_index].clt_idx;
+//    g_hif_sdio_probed_func_list[probed_list_index].interrupted = MTK_WCN_BOOL_TRUE;
+    if ( (registed_list_index >= 0)
+        && (registed_list_index < CFG_CLIENT_COUNT) ) {
+        g_hif_sdio_clt_drv_list[registed_list_index].sdio_cltinfo->hif_clt_irq( CLTCTX(func->device,\
+                                                                    func->num, func->cur_blksize, probed_list_index) );
+    }
+    else {
+    //4 <3> if func has no VALID hif_sdio client's context, release irq for this
+    //4 func and mark it in g_hif_sdio_probed_func_list (remember: donnot claim host in irq contex).
+        HIF_SDIO_WARN_FUNC("release irq (func:0x%p) v(0x%x) d(0x%x) n(0x%x)\n",
+            func, func->vendor, func->device, func->num);
+        mtk_wcn_sdio_irq_flag_set (0);
+        sdio_release_irq(func);
+    }
+
+    return;
+}
+
+/*!
+ * \brief hif_sdio init function
+ *
+ * detailed descriptions
+ *
+ * \retval
+ */
+static int __init hif_sdio_init(void)
+{
+    int   ret = 0;
+    INT32 i   = 0;
+
+    HIF_SDIO_INFO_FUNC("start!\n");
+
+    //4 <1> init all private variables
+    /* init reference count to 0 */
+    gRefCount = 0;
+
+    /* init spin lock information */
+    spin_lock_init( &g_hif_sdio_lock_info.probed_list_lock );
+    spin_lock_init( &g_hif_sdio_lock_info.clt_list_lock );
+
+    /* init probed function list and g_hif_sdio_clt_drv_list */
+    for ( i=0; i<CFG_CLIENT_COUNT; i++ )
+    {
+        hif_sdio_init_probed_list(i);
+        hif_sdio_init_clt_list(i);
+    }
+
+    //4 <2> register to mmc driver
+    ret = sdio_register_driver(&mtk_sdio_client_drv);
+    HIF_SDIO_INFO_FUNC("sdio_register_driver() ret=%d\n", ret);
+       
+       //4 <3> create thread for query chip id and device node for launcher to access
+       if (0 == hifsdiod_start())
+       {
+        hif_sdio_create_dev_node();
+       }
+    HIF_SDIO_DBG_FUNC("end!\n");
+    return ret;
+}
+
+/*!
+ * \brief hif_sdio init function
+ *
+ * detailed descriptions
+ *
+ * \retval
+ */
+static VOID __exit hif_sdio_exit(void)
+{
+    HIF_SDIO_INFO_FUNC("start!\n");
+       
+       hif_sdio_remove_dev_node();
+
+       hifsdiod_stop();
+    //4 <0> if client driver is not removed yet, we shall NOT be called...
+
+    //4 <1> check reference count
+    if ( gRefCount !=0  )
+    {
+        HIF_SDIO_WARN_FUNC("gRefCount=%d !!!\n", gRefCount);
+    }
+
+    //4 <2> check if there is any hif_sdio-registered clients. There should be
+    //4 no registered client...
+
+    //4 <3> Reregister with mmc driver. Our remove handler hif_sdio_remove()
+    //4 will be called later by mmc_core. Clean up driver resources there.
+    sdio_unregister_driver(&mtk_sdio_client_drv);
+
+    HIF_SDIO_DBG_FUNC("end!\n");
+    return;
+} /* end of exitWlan() */
+
+/*!
+ * \brief stp on by wmt (probe client driver).
+ *
+ *
+ * \param none.
+ *
+ * \retval 0:success, -11:not probed, -12:already on, -13:not registered, other errors.
+ */
+INT32 hif_sdio_stp_on(
+    void
+    )
+{
+#if 0
+    MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO *clt_probe_worker_info = 0;
+#endif
+    INT32 clt_index = -1;
+    INT32 probe_index = -1;
+    struct sdio_func *func = 0;
+    int ret = -1;
+    int ret2 = -1;
+
+    HIF_SDIO_INFO_FUNC("start!\n");
+
+    //4 <1> If stp client drv has not been probed, return error code
+    /* MT6620 */
+    if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020B, 1)) >= 0 )
+    {
+        goto stp_on_exist;
+    }
+    if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020C, 1)) >= 0 )
+    {
+        goto stp_on_exist;
+    }
+
+    /* MT6628 */
+    if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6628, 2)) >= 0 )
+    {
+        goto stp_on_exist;
+    }
+    /* MT6619 */
+    if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6619, 1)) >= 0 )
+    {
+        goto stp_on_exist;
+    }
+
+    /* MT6618 */
+    if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018B, 1)) >= 0 )
+    {
+        goto stp_on_exist;
+    }
+    if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018C, 1)) >= 0 )
+    {
+        goto stp_on_exist;
+    }
+    else
+    {
+        //4 <2> If stp client drv has not been probed, return error code
+        /* client func has not been probed */
+        HIF_SDIO_INFO_FUNC("no supported func probed \n");
+        return HIF_SDIO_ERR_NOT_PROBED;
+    }
+
+stp_on_exist:
+    //4 <3> If stp client drv has been on by wmt, return error code
+    if (MTK_WCN_BOOL_FALSE != g_hif_sdio_probed_func_list[probe_index].on_by_wmt) {
+       HIF_SDIO_INFO_FUNC("already on...\n");
+       return HIF_SDIO_ERR_ALRDY_ON;
+    }
+    else {
+        g_hif_sdio_probed_func_list[probe_index].on_by_wmt = MTK_WCN_BOOL_TRUE;
+    }
+
+    if ( (clt_index = g_hif_sdio_probed_func_list[probe_index].clt_idx) >= 0 )    /* the function has been registered */
+    {
+       g_hif_sdio_probed_func_list[probe_index].sdio_irq_enabled = MTK_WCN_BOOL_FALSE;
+        //4 <4> claim irq for this function
+        func = g_hif_sdio_probed_func_list[probe_index].func;
+        sdio_claim_host(func);
+        ret = sdio_claim_irq(func, hif_sdio_irq);
+        mtk_wcn_sdio_irq_flag_set (1);
+        sdio_release_host(func);
+        if (ret) {
+            HIF_SDIO_WARN_FUNC("sdio_claim_irq() for stp fail(%d)\n", ret);
+            return ret;
+        }
+        HIF_SDIO_INFO_FUNC("sdio_claim_irq() for stp ok\n");
+
+        //4 <5> If this struct sdio_func *func is supported by any driver in
+        //4 g_hif_sdio_clt_drv_list, schedule another task to call client's .hif_clt_probe()
+        // TODO: [FixMe][George] WHY probe worker is removed???
+#if 1
+        /* Call client's .hif_clt_probe() */
+        ret = hif_sdio_clt_probe_func(&g_hif_sdio_clt_drv_list[clt_index], probe_index);
+        if (ret) {
+            HIF_SDIO_WARN_FUNC("clt_probe_func() for stp fail(%d) release irq\n", ret);
+            sdio_claim_host(func);
+            mtk_wcn_sdio_irq_flag_set (0);
+            ret2 = sdio_release_irq(func);
+            sdio_release_host(func);
+            if (ret2) {
+                HIF_SDIO_WARN_FUNC("sdio_release_irq() for stp fail(%d)\n", ret2);
+            }
+
+            g_hif_sdio_probed_func_list[probe_index].on_by_wmt = MTK_WCN_BOOL_FALSE;
+            return ret;
+        }
+        HIF_SDIO_INFO_FUNC("ok!\n");
+
+        return 0;
+#else
+        /* use worker thread to perform the client's .hif_clt_probe() */
+        clt_probe_worker_info = vmalloc( sizeof(MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO) );
+        INIT_WORK( &clt_probe_worker_info->probe_work, hif_sdio_clt_probe_worker );
+        clt_probe_worker_info->registinfo_p = &g_hif_sdio_clt_drv_list[clt_index];
+        clt_probe_worker_info->probe_idx = probe_index;
+        schedule_work( &clt_probe_worker_info->probe_work );
+#endif
+    }
+    else {
+        // TODO: [FixMe][George] check if clt_index is cleared in client's unregister function
+        HIF_SDIO_WARN_FUNC("probed but not registered yet (%d)\n", ret);
+        return HIF_SDIO_ERR_CLT_NOT_REG;
+    }
+}
+
+/*!
+ * \brief stp off by wmt (remove client driver).
+ *
+ *
+ * \param none.
+ *
+ * \retval 0:success, -11:not probed, -12:already off, -13:not registered, other errors.
+ */
+INT32 hif_sdio_stp_off(
+    void
+    )
+{
+    INT32 clt_index = -1;
+    INT32 probe_index = -1;
+    struct sdio_func *func = 0;
+    int ret = -1;
+    int ret2 = -1;
+
+    HIF_SDIO_INFO_FUNC("start!\n");
+
+    //4 <1> If stp client drv has not been probed, return error code
+    /* MT6620 */
+    if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020B, 1)) >= 0 )
+    {
+        goto stp_off_exist;
+    }
+    if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020C, 1)) >= 0 )
+    {
+        goto stp_off_exist;
+    }
+    
+    /* MT6628 */
+    if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6628, 2)) >= 0 )
+    {
+        goto stp_off_exist;
+    }
+
+    /* MT6619 */
+    if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6619, 1)) >= 0 )
+    {
+        goto stp_off_exist;
+    }
+
+    /* MT6618 */
+    if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018B, 1)) >= 0 )
+    {
+        goto stp_off_exist;
+    }
+    if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018C, 1)) >= 0 )
+    {
+        goto stp_off_exist;
+    }
+    else
+    {
+        //4 <2> If stp client drv has not been probed, return error code
+        /* client func has not been probed */
+        return HIF_SDIO_ERR_NOT_PROBED;
+    }
+
+stp_off_exist:
+    //4 <3> If stp client drv has been off by wmt, return error code
+    if (MTK_WCN_BOOL_FALSE == g_hif_sdio_probed_func_list[probe_index].on_by_wmt) {
+        HIF_SDIO_WARN_FUNC("already off...\n");
+        return HIF_SDIO_ERR_ALRDY_OFF;
+    }
+    else {
+        g_hif_sdio_probed_func_list[probe_index].on_by_wmt = MTK_WCN_BOOL_FALSE;
+    }
+
+#if 0 // TODO: [FixMe][George] moved below as done in stp_on.
+    //4 <4> release irq for this function
+    func = g_hif_sdio_probed_func_list[probe_index].func;
+    sdio_claim_host(func);
+    ret = sdio_release_irq(func);
+    sdio_release_host(func);
+    if (ret) {
+        printk(KERN_WARNING DRV_NAME "sdio_release_irq for stp fail(%d)\n", ret);
+    }
+    else {
+        printk(KERN_INFO DRV_NAME "sdio_release_irq for stp ok\n");
+    }
+#endif
+
+    if ( (clt_index = g_hif_sdio_probed_func_list[probe_index].clt_idx) >= 0 )    /* the function has been registered */
+    {
+        func = g_hif_sdio_probed_func_list[probe_index].func;
+        
+        //4 <4> Callback to client driver's remove() func
+        ret = g_hif_sdio_clt_drv_list[clt_index].sdio_cltinfo->hif_clt_remove(
+            CLTCTX(func->device, func->num, func->cur_blksize, probe_index) );
+        if (ret) {
+            HIF_SDIO_WARN_FUNC("clt_remove for stp fail(%d)\n", ret);
+        }
+        else {
+            HIF_SDIO_INFO_FUNC("ok!\n");
+        }
+        
+        //4 <5> release irq for this function
+        sdio_claim_host(func);
+        mtk_wcn_sdio_irq_flag_set (0);
+        ret2 = sdio_release_irq(func);
+        sdio_release_host(func);
+               
+        g_hif_sdio_probed_func_list[probe_index].sdio_irq_enabled = MTK_WCN_BOOL_FALSE;
+        if (ret2) {
+            HIF_SDIO_WARN_FUNC("sdio_release_irq() for stp fail(%d)\n", ret2);
+        }
+        else {
+            HIF_SDIO_INFO_FUNC("sdio_release_irq() for stp ok\n");
+        }
+               
+        return (ret + ret2);
+    }
+    else {
+        // TODO: [FixMe][George] check if clt_index is cleared in client's unregister function
+        HIF_SDIO_WARN_FUNC("probed but not registered yet (%d)\n", ret);
+        return HIF_SDIO_ERR_CLT_NOT_REG;
+    }
+}
+
+/*!
+ * \brief wifi on by wmt (probe client driver).
+ *
+ *
+ * \param none.
+ *
+ * \retval 0:success, -11:not probed, -12:already on, -13:not registered, other errors.
+ */
+INT32
+hif_sdio_wifi_on (void)
+{
+#if 0
+    MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO *clt_probe_worker_info = 0;
+#endif
+    INT32 clt_index = -1;
+    INT32 probe_index = -1;
+    struct sdio_func *func = 0;
+    int ret = 0;
+    int ret2 = 0;
+
+    HIF_SDIO_INFO_FUNC("start!\n");
+
+    //4 <1> If wifi client drv has not been probed, return error code
+    /* MT6620 */
+    if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020A, 1)) >= 0 )
+    {
+        goto wifi_on_exist;
+    }
+    if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020C, 2)) >= 0 )
+    {
+        goto wifi_on_exist;
+    }
+     /* MT6628 */
+    if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6628, 1)) >= 0 )
+    {
+        goto wifi_on_exist;
+    }
+    /* MT6618 */
+    if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018A, 1)) >= 0 )
+    {
+        goto wifi_on_exist;
+    }
+    if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018C, 2)) >= 0 )
+    {
+        goto wifi_on_exist;
+    }
+    else
+    {
+        //4 <2> If wifi client drv has not been probed, return error code
+        /* client func has not been probed */
+        return HIF_SDIO_ERR_NOT_PROBED;
+    }
+
+wifi_on_exist:
+    //4 <3> If wifi client drv has been on by wmt, return error code
+    if (g_hif_sdio_probed_func_list[probe_index].on_by_wmt) {
+        HIF_SDIO_INFO_FUNC("probe_index (%d), already on...\n", probe_index);
+        return HIF_SDIO_ERR_ALRDY_ON;
+    }
+
+    if ( (clt_index = g_hif_sdio_probed_func_list[probe_index].clt_idx) >= 0 )    /* the function has been registered */
+    {
+         g_hif_sdio_probed_func_list[probe_index].sdio_irq_enabled = MTK_WCN_BOOL_FALSE;
+        //4 <4> claim irq for this function
+        func = g_hif_sdio_probed_func_list[probe_index].func;
+        sdio_claim_host(func);
+        ret = sdio_claim_irq(func, hif_sdio_irq);
+        mtk_wcn_sdio_irq_flag_set (1);
+        sdio_release_host(func);
+        if (ret) {
+            HIF_SDIO_WARN_FUNC("sdio_claim_irq() for wifi fail(%d)\n", ret);
+            return ret;
+        }
+        HIF_SDIO_INFO_FUNC("sdio_claim_irq() for wifi ok\n");
+
+        //4 <5> If this struct sdio_func *func is supported by any driver in
+        //4 g_hif_sdio_clt_drv_list, schedule another task to call client's .hif_clt_probe()
+        // TODO: [FixMe][George] WHY probe worker is removed???
+#if 1
+        /* Call client's .hif_clt_probe() */
+        ret = hif_sdio_clt_probe_func(&g_hif_sdio_clt_drv_list[clt_index], probe_index);
+        if (ret) {
+            HIF_SDIO_WARN_FUNC("clt_probe_func() for wifi fail(%d) release irq\n", ret);
+            sdio_claim_host(func);
+            mtk_wcn_sdio_irq_flag_set (0);
+            ret2 = sdio_release_irq(func);
+            sdio_release_host(func);
+            if (ret2) {
+                HIF_SDIO_WARN_FUNC("sdio_release_irq() for wifi fail(%d)\n", ret2);
+            }
+
+            g_hif_sdio_probed_func_list[probe_index].on_by_wmt = MTK_WCN_BOOL_FALSE;
+            return ret;
+        }
+        else
+        {
+            g_hif_sdio_probed_func_list[probe_index].on_by_wmt = MTK_WCN_BOOL_TRUE;
+        }
+        HIF_SDIO_INFO_FUNC("ok!\n");
+        return 0;
+#else
+        /* use worker thread to perform the client's .hif_clt_probe() */
+        clt_probe_worker_info = vmalloc( sizeof(MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO) );
+        INIT_WORK( &clt_probe_worker_info->probe_work, hif_sdio_clt_probe_worker );
+        clt_probe_worker_info->registinfo_p = &g_hif_sdio_clt_drv_list[clt_index];
+        clt_probe_worker_info->probe_idx = probe_index;
+        schedule_work( &clt_probe_worker_info->probe_work );
+#endif
+    }
+    else {
+        // TODO: [FixMe][George] check if clt_index is cleared in client's unregister function
+        HIF_SDIO_WARN_FUNC("probed but not registered yet (%d)\n", ret);
+        return HIF_SDIO_ERR_CLT_NOT_REG;
+    }
+}
+
+/*!
+ * \brief wifi off by wmt (remove client driver).
+ *
+ *
+ * \param none.
+ *
+ * \retval 0:success, -11:not probed, -12:already off, -13:not registered, other errors.
+ */
+INT32 hif_sdio_wifi_off(
+    void
+    )
+{
+    INT32 clt_index = -1;
+    INT32 probe_index = -1;
+    struct sdio_func *func = 0;
+    int ret = -1;
+    int ret2 = -1;
+
+    HIF_SDIO_INFO_FUNC("start!\n");
+
+    //4 <1> If wifi client drv has not been probed, return error code
+    /* MT6620 */
+    if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020A, 1)) >= 0 )
+    {
+        goto wifi_off_exist;
+    }
+    if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020C, 2)) >= 0 )
+    {
+        goto wifi_off_exist;
+    }
+
+    /* MT6628 */
+    if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6628, 1)) >= 0 )
+    {
+        goto wifi_off_exist;
+    }
+    
+    /* MT6618 */
+    if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018A, 1)) >= 0 )
+    {
+        goto wifi_off_exist;
+    }
+    if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018C, 2)) >= 0 )
+    {
+        goto wifi_off_exist;
+    }
+    else
+    {
+        //4 <2> If wifi client drv has not been probed, return error code
+        /* client func has not been probed */
+        return HIF_SDIO_ERR_NOT_PROBED;
+    }
+
+wifi_off_exist:
+    //4 <3> If wifi client drv has been off by wmt, return error code
+    if (MTK_WCN_BOOL_FALSE == g_hif_sdio_probed_func_list[probe_index].on_by_wmt) {
+        HIF_SDIO_WARN_FUNC("already off...\n");
+        return HIF_SDIO_ERR_ALRDY_OFF;
+    }
+    else {
+        g_hif_sdio_probed_func_list[probe_index].on_by_wmt = MTK_WCN_BOOL_FALSE;
+    }
+
+#if 0 // TODO: [FixMe][George] moved below as done in wifi_on.
+    //4 <4> release irq for this function
+    func = g_hif_sdio_probed_func_list[probe_index].func;
+    sdio_claim_host(func);
+    ret = sdio_release_irq(func);
+    sdio_release_host(func);
+    if (ret) {
+        printk(KERN_WARNING DRV_NAME "sdio_release_irq for wifi fail(%d)\n", ret);
+    }
+    else {
+        printk(KERN_INFO DRV_NAME "sdio_release_irq for wifi ok\n");
+    }
+#endif
+
+    if ( (clt_index = g_hif_sdio_probed_func_list[probe_index].clt_idx) >= 0 )    /* the function has been registered */
+    {
+        func = g_hif_sdio_probed_func_list[probe_index].func;
+
+        //4 <4> Callback to client driver's remove() func
+        ret = g_hif_sdio_clt_drv_list[clt_index].sdio_cltinfo->hif_clt_remove(
+            CLTCTX(func->device, func->num, func->cur_blksize, probe_index) );
+        if (ret) {
+            HIF_SDIO_WARN_FUNC("clt_remove for wifi fail(%d)\n", ret);
+        }
+        else {
+            HIF_SDIO_INFO_FUNC("ok!\n");
+        }
+
+        //4 <5> release irq for this function
+        sdio_claim_host(func);
+        mtk_wcn_sdio_irq_flag_set (0);
+        ret2 = sdio_release_irq(func);
+        sdio_release_host(func);
+               g_hif_sdio_probed_func_list[probe_index].sdio_irq_enabled = MTK_WCN_BOOL_FALSE;
+        if (ret2) {
+            HIF_SDIO_WARN_FUNC("sdio_release_irq() for wifi fail(%d)\n", ret2);
+        }
+        else {
+            HIF_SDIO_INFO_FUNC("sdio_release_irq() for wifi ok\n");
+        }
+        return (ret + ret2);
+    }
+    else {
+        // TODO: [FixMe][George] check if clt_index is cleared in client's unregister function
+        HIF_SDIO_WARN_FUNC("probed but not registered yet (%d)\n", ret);
+        return HIF_SDIO_ERR_CLT_NOT_REG;
+    }
+}
+
+/*!
+ * \brief set mmc power up/off
+ *
+ * detailed descriptions
+ *
+ * \param: 1. ctx client's context variable, 2.power state: 1:power up, other:power off
+ *
+ * \retval 0:success, -1:fail
+ */
+INT32 mtk_wcn_hif_sdio_bus_set_power (
+    MTK_WCN_HIF_SDIO_CLTCTX ctx,
+    UINT32 pwrState
+    )
+{
+    int probe_index = -1;
+    struct sdio_func *func = 0;
+
+    HIF_SDIO_INFO_FUNC("turn Bus Power to: %d\n", pwrState);
+
+    probe_index = CLTCTX_IDX(ctx);
+    func = g_hif_sdio_probed_func_list[probe_index].func;
+
+    if ( !func )
+    {
+        HIF_SDIO_WARN_FUNC("Cannot find sdio_func !!!\n");
+        return -1;
+    }
+
+    if ( 1 == pwrState )
+    {
+        sdio_claim_host( func );
+        mmc_power_up_ext( func->card->host );
+        sdio_release_host( func );
+        HIF_SDIO_WARN_FUNC("SDIO BUS Power UP\n");
+    }
+    else
+    {
+        sdio_claim_host( func );
+        mmc_power_off_ext( func->card->host );
+        sdio_release_host( func );
+        HIF_SDIO_WARN_FUNC("SDIO BUS Power OFF\n");
+    }
+
+    return 0;
+}
+
+void mtk_wcn_hif_sdio_enable_irq(
+    MTK_WCN_HIF_SDIO_CLTCTX ctx,
+    MTK_WCN_BOOL enable
+    )
+{
+    UINT8 probed_idx = CLTCTX_IDX(ctx);
+
+    if (unlikely(!CLTCTX_IDX_VALID(probed_idx))) {   /* invalid index in CLTCTX */
+        HIF_SDIO_WARN_FUNC("invalid idx in ctx(0x%x), sdio_irq no change\n", ctx);
+        return;
+    }
+
+    /* store client driver's private data to dev driver */
+    g_hif_sdio_probed_func_list[probed_idx].sdio_irq_enabled = enable;
+    smp_wmb();
+    HIF_SDIO_INFO_FUNC("ctx(0x%x) sdio irq enable(%d)\n",
+        ctx, (MTK_WCN_BOOL_FALSE == enable) ? 0 : 1);
+
+
+}
+
+module_init(hif_sdio_init);
+module_exit(hif_sdio_exit);
+
+EXPORT_SYMBOL(mtk_wcn_hif_sdio_update_cb_reg);
+EXPORT_SYMBOL(mtk_wcn_hif_sdio_client_reg);
+EXPORT_SYMBOL(mtk_wcn_hif_sdio_client_unreg);
+EXPORT_SYMBOL(mtk_wcn_hif_sdio_readb);
+EXPORT_SYMBOL(mtk_wcn_hif_sdio_writeb);
+EXPORT_SYMBOL(mtk_wcn_hif_sdio_readl);
+EXPORT_SYMBOL(mtk_wcn_hif_sdio_writel);
+EXPORT_SYMBOL(mtk_wcn_hif_sdio_read_buf);
+EXPORT_SYMBOL(mtk_wcn_hif_sdio_write_buf);
+EXPORT_SYMBOL(mtk_wcn_hif_sdio_set_drvdata);
+EXPORT_SYMBOL(mtk_wcn_hif_sdio_get_drvdata);
+EXPORT_SYMBOL(mtk_wcn_hif_sdio_wmt_control);
+EXPORT_SYMBOL(mtk_wcn_hif_sdio_bus_set_power);
+EXPORT_SYMBOL(mtk_wcn_hif_sdio_get_dev);
+EXPORT_SYMBOL(mtk_wcn_hif_sdio_enable_irq); 
+
+
diff --git a/drivers/mtk_wcn_combo/common/linux/hif_sdio_chrdev.c b/drivers/mtk_wcn_combo/common/linux/hif_sdio_chrdev.c
new file mode 100755 (executable)
index 0000000..42123e6
--- /dev/null
@@ -0,0 +1,354 @@
+#include "hif_sdio.h"
+#include "hif_sdio_chrdev.h"
+
+
+
+static int hif_sdio_proc(void * pvData);
+static int hif_sdio_open(struct inode *inode, struct file *file);
+static int hif_sdio_release(struct inode *inode, struct file *file);
+static long hif_sdio_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
+static ssize_t hif_sdio_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos);
+
+
+
+unsigned int hifSdioMajor = 0;
+
+#define COMBO_IOC_MAGIC        'h'
+#define COMBO_IOCTL_GET_CHIP_ID  _IOR(COMBO_IOC_MAGIC, 0, int)
+#define COMBO_IOCTL_SET_CHIP_ID  _IOW(COMBO_IOC_MAGIC, 1, int)
+
+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},
+
+};
+
+
+
+struct file_operations hifDevOps = 
+{
+       .owner = THIS_MODULE,
+       .open = hif_sdio_open,
+       .release = hif_sdio_release,
+       .unlocked_ioctl = hif_sdio_unlocked_ioctl,
+       .read = hif_sdio_read,
+};
+
+struct class *pHifClass = NULL;
+struct device *pHifDev = NULL;
+UCHAR *HifClassName = "hifsdiod";
+UCHAR *kObjName = "hifsdiod";
+
+
+struct task_struct *gConIdQueryThread;
+wait_queue_head_t gHifsdiodEvent;
+
+//OSAL_THREAD           gConIdQueryThread;
+//OSAL_EVENT            gHifsdiodEvent;
+UCHAR *gConIdQueryName = "consys-id-query";
+INT32 gComboChipId = -1;
+
+
+
+INT32 hifsdiod_start(void)
+{
+    int iRet = -1;
+       init_waitqueue_head(&gHifsdiodEvent);
+#if 0
+    osal_event_init(&gHifsdiodEvent);
+    gConIdQueryThread.pThreadData = (VOID *)NULL;
+    gConIdQueryThread.pThreadFunc = (VOID *)hif_sdio_proc;
+    osal_memcpy(gConIdQueryThread.threadName, gConIdQueryName , osal_strlen(gConIdQueryName));
+       
+
+    iRet = osal_thread_create(&gConIdQueryThread);
+    if (iRet < 0) 
+    {
+        HIF_SDIO_ERR_FUNC("osal_thread_create fail...\n");
+        goto ERR_EXIT1;
+    }
+#else
+    gConIdQueryThread = kthread_create(hif_sdio_proc, NULL, gConIdQueryName);
+    if (NULL == gConIdQueryThread) 
+    {
+        HIF_SDIO_ERR_FUNC("osal_thread_create fail...\n");
+        goto ERR_EXIT1;
+    }
+
+#endif
+
+#if 0
+    /* Start STPd thread*/
+    iRet = osal_thread_run(&gConIdQueryThread);
+    if(iRet < 0)
+    {
+        HIF_SDIO_ERR_FUNC("osal_thread_run FAILS\n");
+        goto ERR_EXIT1;
+    }
+#else
+    if (gConIdQueryThread) {
+        wake_up_process(gConIdQueryThread);
+    }
+       else
+       {
+           goto ERR_EXIT1;
+       }
+#endif
+    iRet = 0;
+       HIF_SDIO_INFO_FUNC("succeed\n");
+
+       return iRet;
+       
+ERR_EXIT1:
+       HIF_SDIO_ERR_FUNC("failed\n");
+       return iRet;
+ }
+
+
+INT32 hifsdiod_stop(void)
+{
+    if (gConIdQueryThread) {
+               HIF_SDIO_INFO_FUNC("inform hifsdiod exit..\n");
+        kthread_stop(gConIdQueryThread);
+               gConIdQueryThread = NULL;
+    }
+       return 0;
+}
+
+
+static int hif_sdio_proc(void * pvData)
+{
+    while (!kthread_should_stop()) 
+    {
+        //HIF_SDIO_INFO_FUNC("enter sleep.\n");
+               osal_msleep(10000);
+               //HIF_SDIO_INFO_FUNC("wakeup\n");               
+    }
+    HIF_SDIO_INFO_FUNC("hifsdiod exit.\n"); 
+       return 0;
+}
+
+
+static int hif_sdio_open(struct inode *inode, struct file *file)
+{
+    HIF_SDIO_INFO_FUNC(" ++\n");
+       HIF_SDIO_INFO_FUNC(" --\n");
+       return 0;
+}
+
+static int hif_sdio_release(struct inode *inode, struct file *file)
+{
+    HIF_SDIO_INFO_FUNC(" ++\n");
+       HIF_SDIO_INFO_FUNC(" --\n");
+
+       return 0;
+}
+
+
+static ssize_t hif_sdio_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
+
+{
+    HIF_SDIO_INFO_FUNC(" ++\n");
+       HIF_SDIO_INFO_FUNC(" --\n");
+
+    return 0;
+}
+
+static long hif_sdio_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+    int retval = 0;
+
+    HIF_SDIO_DBG_FUNC("cmd (%d)\n", cmd);
+
+    switch(cmd)
+    {
+        case COMBO_IOCTL_GET_CHIP_ID:
+                       gComboChipId = 0x6628;
+                       retval = gComboChipId;
+                       HIF_SDIO_INFO_FUNC("get combo chip id: 0x%x\n", gComboChipId);
+                       break;
+               case COMBO_IOCTL_SET_CHIP_ID:
+                       gComboChipId = arg;
+                       HIF_SDIO_INFO_FUNC("set combo chip id to 0x%x\n", gComboChipId);
+                       break;
+               default:
+                       HIF_SDIO_WARN_FUNC("unknown cmd (%d)\n", cmd);
+                       retval = 0;
+                       break;
+    }
+       return retval;
+}
+       
+
+INT32 hif_sdio_is_chipid_valid (INT32 chipId)
+{
+       INT32 index = -1;
+       
+    INT32 left = 0;
+       INT32 middle = 0;
+    INT32 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)
+    {
+       HIF_SDIO_ERR_FUNC("no supported chipid found\n");
+    }
+       else
+       {
+               HIF_SDIO_INFO_FUNC("index:%d, chipId:0x%x\n", index, gChipInfoArray[index].chipId);
+       }
+
+       return index;
+}
+
+INT32 hif_sdio_match_chipid_by_dev_id (const struct sdio_device_id *id)
+{
+    INT32 maxIndex = sizeof (gChipInfoArray) / sizeof (gChipInfoArray[0]);
+    INT32 index = 0;
+    struct sdio_device_id *localId = NULL;
+       INT32 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;
+                       HIF_SDIO_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;
+               break;
+           }
+       }
+       if (0 > chipId)
+       {
+           HIF_SDIO_ERR_FUNC("No valid chipId found, vendor id(0x%x), device id(0x%x)\n", id->vendor, id->device);
+       }
+       
+    return chipId;
+}
+
+
+INT32 mtk_wcn_hif_sdio_query_chipid(INT32 waitFlag)
+{
+    UINT32 timeSlotMs = 200;
+       UINT32 maxTimeSlot = 15;
+       UINT32 counter = 0;
+    //gComboChipId = 0x6628;
+    if (0 == waitFlag)
+               return gComboChipId;
+       if (0 <= hif_sdio_is_chipid_valid(gComboChipId))
+               return gComboChipId;
+    wmt_plat_pwr_ctrl(FUNC_ON);
+       wmt_plat_sdio_ctrl(WMT_SDIO_SLOT_SDIO1, FUNC_ON);
+       while (counter < maxTimeSlot)
+       {
+           if (0 <= hif_sdio_is_chipid_valid(gComboChipId))
+                       break;
+           osal_msleep(timeSlotMs);
+           counter++;
+       }
+       
+       wmt_plat_sdio_ctrl(WMT_SDIO_SLOT_SDIO1, FUNC_OFF);
+       wmt_plat_pwr_ctrl(FUNC_OFF);
+       return gComboChipId;
+}
+EXPORT_SYMBOL(mtk_wcn_hif_sdio_query_chipid);
+
+INT32 mtk_wcn_hif_sdio_tell_chipid(INT32 chipId)
+{
+
+       gComboChipId = chipId;
+    HIF_SDIO_INFO_FUNC("set combo chip id to 0x%x\n", gComboChipId);
+
+       return gComboChipId;
+}
+EXPORT_SYMBOL(mtk_wcn_hif_sdio_tell_chipid);
+
+INT32 hif_sdio_create_dev_node(void)
+{
+
+       INT32 iResult = -1;
+       
+       HIF_SDIO_DBG_FUNC( "++");
+       iResult = register_chrdev(hifSdioMajor, kObjName, &hifDevOps);
+       if(0 > iResult)
+       {
+               HIF_SDIO_ERR_FUNC("register_chrdev failed.\n");
+               iResult = -1;
+       }
+       else
+       {
+               hifSdioMajor = hifSdioMajor == 0 ? iResult : hifSdioMajor;
+               HIF_SDIO_INFO_FUNC("register_chrdev succeed, mtk_jajor = %d\n", hifSdioMajor);
+               pHifClass = class_create(THIS_MODULE, HifClassName);
+               if(IS_ERR(pHifClass))
+               {
+                       HIF_SDIO_ERR_FUNC("class_create error\n");
+                       iResult = -2;
+               }
+               else
+               {
+                       pHifDev = device_create(pHifClass, NULL, MKDEV(hifSdioMajor, 0), NULL, HifClassName, "%d", 0);
+                       if(IS_ERR(pHifDev))
+                       {
+                               HIF_SDIO_ERR_FUNC("device_create error:%ld\n", PTR_ERR(pHifDev));
+                               iResult = -3;
+                       }
+                       else
+                       {
+                           HIF_SDIO_INFO_FUNC("device_create succeed\n");
+                           iResult = 0;
+                       }
+               }
+       }
+    return iResult;
+}
+
+
+INT32 hif_sdio_remove_dev_node(void)
+{
+    if(pHifDev != NULL)
+       {
+               device_destroy(pHifClass, MKDEV(hifSdioMajor, 0));
+               pHifDev = NULL;
+       }
+       if(pHifClass != NULL)
+       {
+               class_destroy(pHifClass);
+               pHifClass = NULL;
+       }
+       
+       if(hifSdioMajor != 0)
+       {
+               unregister_chrdev(hifSdioMajor, kObjName);
+               hifSdioMajor = 0;
+       }
+    return 0;
+}
+
+
diff --git a/drivers/mtk_wcn_combo/common/linux/include/hif_sdio.h b/drivers/mtk_wcn_combo/common/linux/include/hif_sdio.h
new file mode 100755 (executable)
index 0000000..4751937
--- /dev/null
@@ -0,0 +1,311 @@
+/*
+** $Id: $
+*/
+
+/*! \file   "hif_sdio.h"
+    \brief
+
+
+*/
+
+/*
+** $Log: $
+ *
+ * 07 25 2010 george.kuo
+ *
+ * Move hif_sdio driver to linux directory.
+ *
+ * 07 23 2010 george.kuo
+ *
+ * Add MT6620 driver source tree
+ * , including char device driver (wmt, bt, gps), stp driver, interface driver (tty ldisc and hif_sdio), and bt hci driver.
+**
+**
+*/
+
+#ifndef _HIF_SDIO_H
+#define _HIF_SDIO_H
+/*******************************************************************************
+*                         C O M P I L E R   F L A G S
+********************************************************************************
+*/
+#define HIF_SDIO_DEBUG  (0) /* 0:trun off debug msg and assert, 1:trun off debug msg and assert */
+
+/*******************************************************************************
+*                    E X T E R N A L   R E F E R E N C E S
+********************************************************************************
+*/
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
+       
+#include <linux/mm.h>
+#include <linux/firmware.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/vmalloc.h>
+
+
+#include "osal_typedef.h"
+#include "osal.h"
+#include "wmt_exp.h"
+
+
+/*******************************************************************************
+*                              C O N S T A N T S
+********************************************************************************
+*/
+#define CFG_CLIENT_COUNT  (11)
+
+#define HIF_DEFAULT_BLK_SIZE  (256)
+#define HIF_DEFAULT_VENDOR    (0x037A)
+
+#define HIF_SDIO_LOG_LOUD    4
+#define HIF_SDIO_LOG_DBG     3
+#define HIF_SDIO_LOG_INFO    2
+#define HIF_SDIO_LOG_WARN    1
+#define HIF_SDIO_LOG_ERR     0
+
+
+/*******************************************************************************
+*                             D A T A   T Y P E S
+********************************************************************************
+*/
+
+/* Function info provided by client driver */
+typedef struct _MTK_WCN_HIF_SDIO_FUNCINFO MTK_WCN_HIF_SDIO_FUNCINFO;
+
+/* Client context provided by hif_sdio driver for the following function call */
+typedef UINT32 MTK_WCN_HIF_SDIO_CLTCTX;
+
+/* Callback functions provided by client driver */
+typedef INT32 (*MTK_WCN_HIF_SDIO_PROBE)(MTK_WCN_HIF_SDIO_CLTCTX, const MTK_WCN_HIF_SDIO_FUNCINFO *);
+typedef INT32 (*MTK_WCN_HIF_SDIO_REMOVE)(MTK_WCN_HIF_SDIO_CLTCTX);
+typedef INT32 (*MTK_WCN_HIF_SDIO_IRQ)(MTK_WCN_HIF_SDIO_CLTCTX);
+
+/* Function info provided by client driver */
+struct _MTK_WCN_HIF_SDIO_FUNCINFO {
+    UINT16 manf_id;    /* TPLMID_MANF: manufacturer ID */
+    UINT16 card_id;    /* TPLMID_CARD: card ID */
+    UINT16 func_num;    /* Function Number */
+    UINT16 blk_sz;    /* Function block size */
+};
+
+/* Client info provided by client driver */
+typedef struct _MTK_WCN_HIF_SDIO_CLTINFO {
+    const MTK_WCN_HIF_SDIO_FUNCINFO *func_tbl; /* supported function info table */
+    UINT32 func_tbl_size; /* supported function table info element number */
+    MTK_WCN_HIF_SDIO_PROBE hif_clt_probe; /* callback function for probing */
+    MTK_WCN_HIF_SDIO_REMOVE hif_clt_remove; /* callback function for removing */
+    MTK_WCN_HIF_SDIO_IRQ hif_clt_irq; /* callback function for interrupt handling */
+} MTK_WCN_HIF_SDIO_CLTINFO;
+
+/* function info provided by registed function */
+typedef struct _MTK_WCN_HIF_SDIO_REGISTINFO {
+    const MTK_WCN_HIF_SDIO_CLTINFO *sdio_cltinfo; /* client's MTK_WCN_HIF_SDIO_CLTINFO pointer */
+    const MTK_WCN_HIF_SDIO_FUNCINFO *func_info; /* supported function info pointer */
+} MTK_WCN_HIF_SDIO_REGISTINFO;
+
+/* Card info provided by probed function */
+typedef struct _MTK_WCN_HIF_SDIO_PROBEINFO {
+    struct sdio_func* func;  /* probed sdio function pointer */
+    void* private_data_p;  /* clt's private data pointer */
+    MTK_WCN_BOOL on_by_wmt;   /* TRUE: on by wmt, FALSE: not on by wmt */
+       /* added for sdio irq sync and mmc single_irq workaround */
+    MTK_WCN_BOOL sdio_irq_enabled; /* TRUE: can handle sdio irq; FALSE: no sdio irq handling */
+    INT8 clt_idx;   /* registered function table info element number (initial value is -1) */
+} MTK_WCN_HIF_SDIO_PROBEINFO;
+
+/* work queue info needed by worker */
+typedef struct _MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO {
+    struct work_struct probe_work;   /* work queue structure */
+    MTK_WCN_HIF_SDIO_REGISTINFO *registinfo_p;  /* MTK_WCN_HIF_SDIO_REGISTINFO pointer of the client */
+    INT8 probe_idx;   /* probed function table info element number (initial value is -1) */
+} MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO;
+
+/* global resource locks info of hif_sdio drv */
+typedef struct _MTK_WCN_HIF_SDIO_LOCKINFO {
+    spinlock_t probed_list_lock;  /* spin lock for probed list */
+    spinlock_t clt_list_lock;  /* spin lock for client registed list */
+} MTK_WCN_HIF_SDIO_LOCKINFO;
+
+/* error code returned by hif_sdio driver (use NEGATIVE number) */
+typedef enum {
+    HIF_SDIO_ERR_SUCCESS = 0,
+    HIF_SDIO_ERR_FAIL = HIF_SDIO_ERR_SUCCESS - 1, /* generic error */
+    HIF_SDIO_ERR_INVALID_PARAM = HIF_SDIO_ERR_FAIL - 1,
+    HIF_SDIO_ERR_DUPLICATED = HIF_SDIO_ERR_INVALID_PARAM - 1,
+    HIF_SDIO_ERR_UNSUP_MANF_ID = HIF_SDIO_ERR_DUPLICATED - 1,
+    HIF_SDIO_ERR_UNSUP_CARD_ID = HIF_SDIO_ERR_UNSUP_MANF_ID - 1,
+    HIF_SDIO_ERR_INVALID_FUNC_NUM = HIF_SDIO_ERR_UNSUP_CARD_ID - 1,
+    HIF_SDIO_ERR_INVALID_BLK_SZ = HIF_SDIO_ERR_INVALID_FUNC_NUM - 1,
+    HIF_SDIO_ERR_NOT_PROBED = HIF_SDIO_ERR_INVALID_BLK_SZ - 1,
+    HIF_SDIO_ERR_ALRDY_ON = HIF_SDIO_ERR_NOT_PROBED -1,
+    HIF_SDIO_ERR_ALRDY_OFF = HIF_SDIO_ERR_ALRDY_ON -1,
+    HIF_SDIO_ERR_CLT_NOT_REG = HIF_SDIO_ERR_ALRDY_OFF - 1,   
+} MTK_WCN_HIF_SDIO_ERR ;
+
+typedef struct _MTK_WCN_HIF_SDIO_CHIP_INFO_
+{
+    struct sdio_device_id deviceId;
+       UINT32 chipId;
+}MTK_WCN_HIF_SDIO_CHIP_INFO, *P_MTK_WCN_HIF_SDIO_CHIP_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
+********************************************************************************
+*/
+
+
+
+/*!
+ * \brief A macro used to describe an SDIO function
+ *
+ * Fill an MTK_WCN_HIF_SDIO_FUNCINFO structure with function-specific information
+ *
+ * \param manf      the 16 bit manufacturer id
+ * \param card      the 16 bit card id
+ * \param func      the 16 bit function number
+ * \param b_sz    the 16 bit function block size
+ */
+#define MTK_WCN_HIF_SDIO_FUNC(manf, card, func, b_sz) \
+    .manf_id = (manf), .card_id = (card), .func_num = (func), .blk_sz = (b_sz)
+
+#ifndef DFT_TAG
+#define DFT_TAG         "[HIF-SDIO]"
+#endif
+
+extern UINT32 gHifSdioDbgLvl;
+
+#define HIF_SDIO_LOUD_FUNC(fmt, arg...)   if (gHifSdioDbgLvl >= HIF_SDIO_LOG_LOUD) { osal_dbg_print(DFT_TAG"[L]%s:"  fmt, __FUNCTION__ ,##arg);}
+#define HIF_SDIO_DBG_FUNC(fmt, arg...)    if (gHifSdioDbgLvl >= HIF_SDIO_LOG_DBG) { osal_dbg_print(DFT_TAG"[D]%s:"  fmt, __FUNCTION__ ,##arg);}
+#define HIF_SDIO_INFO_FUNC(fmt, arg...)   if (gHifSdioDbgLvl >= HIF_SDIO_LOG_INFO) { osal_dbg_print(DFT_TAG"[I]%s:"  fmt, __FUNCTION__ ,##arg);}
+#define HIF_SDIO_WARN_FUNC(fmt, arg...)   if (gHifSdioDbgLvl >= HIF_SDIO_LOG_WARN) { osal_dbg_print(DFT_TAG"[W]%s(%d):"  fmt, __FUNCTION__ , __LINE__, ##arg);}
+#define HIF_SDIO_ERR_FUNC(fmt, arg...)    if (gHifSdioDbgLvl >= HIF_SDIO_LOG_ERR) { osal_dbg_print(DFT_TAG"[E]%s(%d):"  fmt, __FUNCTION__ , __LINE__, ##arg);}
+
+/*!
+ * \brief ASSERT function definition.
+ *
+ */
+#if HIF_SDIO_DEBUG
+#define HIF_SDIO_ASSERT(expr)    if ( !(expr) ) { \
+                            osal_dbg_print("assertion failed! %s[%d]: %s\n",\
+                                __FUNCTION__, __LINE__, #expr); \
+                            osal_bug_on( !(expr) );\
+                        }
+#else
+#define HIF_SDIO_ASSERT(expr)    do {} while(0)
+#endif
+
+/*******************************************************************************
+*                   F U N C T I O N   D E C L A R A T I O N S
+********************************************************************************
+*/
+
+/*!
+ * \brief MTK hif sdio client registration function
+ *
+ * Client uses this function to do hif sdio registration
+ *
+ * \param pinfo     a pointer of client's information
+ *
+ * \retval 0    register successfully
+ * \retval < 0  error code
+ */
+extern INT32 mtk_wcn_hif_sdio_client_reg (
+    const MTK_WCN_HIF_SDIO_CLTINFO *pinfo
+    );
+
+extern INT32 mtk_wcn_hif_sdio_client_unreg (
+    const MTK_WCN_HIF_SDIO_CLTINFO *pinfo
+    );
+
+extern INT32 mtk_wcn_hif_sdio_readb (
+    MTK_WCN_HIF_SDIO_CLTCTX ctx,
+    UINT32 offset,
+    PUINT8 pvb
+    );
+
+extern INT32 mtk_wcn_hif_sdio_writeb (
+    MTK_WCN_HIF_SDIO_CLTCTX ctx,
+    UINT32 offset,
+    UINT8 vb
+    );
+
+extern INT32 mtk_wcn_hif_sdio_readl (
+    MTK_WCN_HIF_SDIO_CLTCTX ctx,
+    UINT32 offset,
+    PUINT32 pvl
+    );
+
+extern INT32 mtk_wcn_hif_sdio_writel (
+    MTK_WCN_HIF_SDIO_CLTCTX ctx,
+    UINT32 offset,
+    UINT32 vl
+    );
+
+extern INT32 mtk_wcn_hif_sdio_read_buf (
+    MTK_WCN_HIF_SDIO_CLTCTX ctx,
+    UINT32 offset,
+    PUINT32 pbuf,
+    UINT32 len
+    );
+
+extern INT32 mtk_wcn_hif_sdio_write_buf (
+    MTK_WCN_HIF_SDIO_CLTCTX ctx,
+    UINT32 offset,
+    PUINT32 pbuf,
+    UINT32 len
+    );
+
+extern void mtk_wcn_hif_sdio_set_drvdata(
+    MTK_WCN_HIF_SDIO_CLTCTX ctx,
+    void* private_data_p
+    );
+
+extern void* mtk_wcn_hif_sdio_get_drvdata(
+    MTK_WCN_HIF_SDIO_CLTCTX ctx
+    );
+
+extern INT32 mtk_wcn_hif_sdio_wmt_control(
+    WMT_SDIO_FUNC_TYPE func_type,
+    MTK_WCN_BOOL is_on
+    );
+
+extern INT32 mtk_wcn_hif_sdio_bus_set_power (
+    MTK_WCN_HIF_SDIO_CLTCTX ctx,
+    UINT32 pwrState
+    );
+
+extern void mtk_wcn_hif_sdio_get_dev(
+    MTK_WCN_HIF_SDIO_CLTCTX ctx,
+    struct device **dev
+    );
+
+extern INT32 mtk_wcn_hif_sdio_update_cb_reg(
+    int (*ts_update)(void)
+    );
+
+
+INT32 mtk_wcn_hif_sdio_tell_chipid(INT32 chipId);
+INT32 mtk_wcn_hif_sdio_query_chipid(INT32 waitFlag);
+
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+#endif /* _HIF_SDIO_H */
+
+
diff --git a/drivers/mtk_wcn_combo/common/linux/include/hif_sdio_chrdev.h b/drivers/mtk_wcn_combo/common/linux/include/hif_sdio_chrdev.h
new file mode 100755 (executable)
index 0000000..1aa756d
--- /dev/null
@@ -0,0 +1,34 @@
+
+#ifndef _HIF_SDIO_CHRDEV_H_
+
+#define _HIF_SDIO_CHRDEV_H_
+
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <asm/current.h>
+#include <linux/kthread.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
+
+
+#include "wmt_exp.h"
+#include "wmt_plat.h"
+#ifdef CFG_WMT_PS_SUPPORT
+#undef CFG_WMT_PS_SUPPORT
+#endif
+
+
+extern INT32 hif_sdio_create_dev_node(void);
+extern INT32 hif_sdio_remove_dev_node(void);
+extern INT32 hifsdiod_start(void);
+extern INT32 hifsdiod_stop(void);
+INT32 hif_sdio_match_chipid_by_dev_id (const struct sdio_device_id *id);
+INT32 hif_sdio_is_chipid_valid (INT32 chipId);
+
+
+
+#endif /*_HIF_SDIO_CHRDEV_H_*/
diff --git a/drivers/mtk_wcn_combo/common/linux/include/mach/mtk_wcn_cmb_stub.h b/drivers/mtk_wcn_combo/common/linux/include/mach/mtk_wcn_cmb_stub.h
new file mode 100755 (executable)
index 0000000..ec4d5f1
--- /dev/null
@@ -0,0 +1,201 @@
+/*! \file
+    \brief  Declaration of library functions
+
+    Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+/*******************************************************************************
+* Copyright (c) 2009 MediaTek Inc.
+*
+* All rights reserved. Copying, compilation, modification, distribution
+* or any other use whatsoever of this material is strictly prohibited
+* except in accordance with a Software License Agreement with
+* MediaTek Inc.
+********************************************************************************
+*/
+
+/*******************************************************************************
+* LEGAL DISCLAIMER
+*
+* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND
+* AGREES THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK
+* SOFTWARE") RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE
+* PROVIDED TO BUYER ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY
+* DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+* LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+* PARTICULAR PURPOSE OR NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE
+* ANY WARRANTY WHATSOEVER WITH RESPECT TO THE SOFTWARE OF ANY THIRD PARTY
+* WHICH MAY BE USED BY, INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK
+* SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY
+* WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE
+* FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S SPECIFICATION OR TO
+* CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL
+* BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT
+* ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY
+* BUYER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT
+* OF LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING
+* THEREOF AND RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN
+* FRANCISCO, CA, UNDER THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE
+* (ICC).
+********************************************************************************
+*/
+
+#ifndef _MTK_WCN_CMB_STUB_H_
+#define _MTK_WCN_CMB_STUB_H_
+
+#include <linux/types.h>
+       typedef enum {
+               COMBO_AUDIO_STATE_0 = 0, /* 0000: BT_PCM_OFF & FM analog (line in/out) */
+               COMBO_AUDIO_STATE_1 = 1, /* 0001: BT_PCM_ON & FM analog (in/out) */
+               COMBO_AUDIO_STATE_2 = 2, /* 0010: BT_PCM_OFF & FM digital (I2S) */
+               COMBO_AUDIO_STATE_3 = 3, /* 0011: BT_PCM_ON & FM digital (I2S) (invalid in 73evb & 1.2 phone configuration) */
+               COMBO_AUDIO_STATE_MAX = 4,
+       } COMBO_AUDIO_STATE;
+       
+       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_MAX,
+       } COMBO_IF;
+       
+       
+       /******************************************************************************
+       *                                       F U N C T I O N   D E C L A R A T I O N S
+       *******************************************************************************
+       */
+       
+       
+       /* [GeorgeKuo] Stub functions for other kernel built-in modules to call.
+        * Keep them unchanged temporarily. Move mt_combo functions to mtk_wcn_combo.
+        */
+       //extern int mt_combo_audio_ctrl_ex(COMBO_AUDIO_STATE state, u32 clt_ctrl);
+       static inline int mt_combo_audio_ctrl(COMBO_AUDIO_STATE state) {
+               //return mt_combo_audio_ctrl_ex(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 board_sdio_ctrl (unsigned int sdio_port_num, unsigned int on);
+//#include <mach/mt_combo.h> jake 
+/*******************************************************************************
+*                         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 {
+    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_MAX = 4,
+} 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 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 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;
+} 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 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);
+
+// TODO: [FixMe][GeorgeKuo]: put prototypes into mt_combo.h for board.c temporarily for non-finished porting
+// TODO: old: rfkill->board.c->mt_combo->wmt_lib_plat
+// TODO: new: rfkill->mtk_wcn_cmb_stub_alps->wmt_plat_alps
+#if 0
+extern int mtk_wcn_cmb_stub_func_ctrl(unsigned int type, unsigned int on);
+#endif
+
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+
+
+#endif /* _MTK_WCN_CMB_STUB_H_ */
+
+
+
+
+
+
diff --git a/drivers/mtk_wcn_combo/common/linux/include/osal.h b/drivers/mtk_wcn_combo/common/linux/include/osal.h
new file mode 100755 (executable)
index 0000000..aa21129
--- /dev/null
@@ -0,0 +1,391 @@
+/*! \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 <linux/version.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/sched.h>
+#include <linux/poll.h>
+#include <asm/current.h>
+#include <asm/uaccess.h>
+#include <linux/proc_fs.h>
+#include <linux/workqueue.h>
+#include <linux/wait.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/vmalloc.h>
+#include <linux/firmware.h>
+#include <linux/kthread.h>
+#include <linux/jiffies.h>
+#include <linux/slab.h>
+#if WMT_PLAT_ALPS
+#include <linux/aee.h>
+#endif
+#include <linux/kfifo.h>
+#include <linux/wakelock.h>
+#include <linux/log2.h>
+#include <osal_typedef.h>
+#include <asm/atomic.h>
+
+/*******************************************************************************
+*                         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
+#define OSAL_OP_DATA_SIZE   32
+#define DBG_LOG_STR_SIZE    512
+
+#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) \
+   { \
+   (prb)->read = (prb)->write = 0; \
+   (prb)->size = (qsize); \
+   }
+
+#define RB_PUT(prb, value) \
+{ \
+    if (!RB_FULL( prb )) { \
+        (prb)->queue[ (prb)->write & RB_MASK(prb) ] = value; \
+        ++((prb)->write); \
+    } \
+    else { \
+        osal_assert(!RB_FULL(prb)); \
+    } \
+}
+
+#define RB_GET(prb, value) \
+{ \
+    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)); \
+    } \
+}
+
+/*******************************************************************************
+*                    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)(ULONG);
+typedef INT32 (*P_COND)(VOID *);
+
+typedef struct _OSAL_TIMER_
+{
+    struct timer_list timer;
+    P_TIMEOUT_HANDLER timeoutHandler;
+    ULONG timeroutHandlerData;
+}OSAL_TIMER, *P_OSAL_TIMER;
+
+typedef struct _OSAL_UNSLEEPABLE_LOCK_
+{
+    spinlock_t lock;
+    ULONG 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
+    UINT32 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_
+{
+   struct wake_lock        wake_lock; 
+   UINT8  name[MAX_WAKE_LOCK_NAME_LEN];
+} OSAL_WAKE_LOCK, *P_OSAL_WAKE_LOCK;
+#if 1
+typedef struct _OSAL_BIT_OP_VAR_
+{
+    ULONG data;
+    OSAL_UNSLEEPABLE_LOCK opLock;
+}OSAL_BIT_OP_VAR, *P_OSAL_BIT_OP_VAR;
+#else
+#define OSAL_BIT_OP_VAR ULONG
+#define P_OSAL_BIT_OP_VAR ULONG*
+
+
+#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 void osal_bug_on(unsigned long val);
+
+extern LONG osal_strtol(const char *str, char **c, UINT32 adecimal);
+extern INT32 osal_snprintf(char *buf, UINT32 len, const char*fmt, ...);
+
+extern INT32 osal_print(const char *str, ...);
+extern INT32 osal_dbg_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_msleep(UINT32 ms);
+
+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);
+
+#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 UINT16 osal_crc16(const UINT8 *buffer, const UINT32 length);
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+
+#define osal_err_print(fmt, arg...) osal_print(KERN_ERR fmt, ##arg)
+#define osal_warn_print(fmt, arg...) osal_print(KERN_ERR fmt, ##arg)
+#define osal_info_print(fmt, arg...) osal_print(KERN_ERR fmt, ##arg)
+#define osal_load_print(fmt, arg...) osal_print(KERN_DEBUG fmt, ##arg)
+#define osal_assert(condition) if (!(condition)) {osal_err_print("%s, %d, (%s)\n", __FILE__, __LINE__, #condition);}
+
+#endif /* _OSAL_H_ */
+
diff --git a/drivers/mtk_wcn_combo/common/linux/include/osal_typedef.h b/drivers/mtk_wcn_combo/common/linux/include/osal_typedef.h
new file mode 100755 (executable)
index 0000000..e486576
--- /dev/null
@@ -0,0 +1,46 @@
+/*! \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_
+
+typedef void VOID;
+typedef void *PVOID;
+
+typedef char CHAR;
+typedef char *PCHAR;
+typedef signed char INT8;
+typedef signed char *PINT8;
+typedef unsigned char UINT8;
+typedef unsigned char *PUINT8;
+typedef unsigned char UCHAR;
+typedef unsigned char  *PUCHAR;
+
+typedef signed short INT16;
+typedef signed short *PINT16;
+typedef unsigned short UINT16;
+typedef unsigned short *PUINT16;
+
+typedef signed long LONG;
+typedef signed long *PLONG;
+
+typedef signed int INT32;
+typedef signed int *PINT32;
+typedef unsigned int UINT32;
+typedef unsigned int *PUINT32;
+
+typedef unsigned long ULONG;
+typedef unsigned long  *PULONG;
+
+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/mtk_wcn_combo/common/linux/include/stp_dbg.h b/drivers/mtk_wcn_combo/common/linux/include/stp_dbg.h
new file mode 100755 (executable)
index 0000000..7a956e3
--- /dev/null
@@ -0,0 +1,229 @@
+#ifndef _STP_DEBUG_H_
+#define _STP_DEBUG_H_
+
+#include <linux/time.h>
+#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 2048
+#define STP_DBG_LOG_ENTRY_SZ  2048
+
+#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>",
+    "<GPS>",
+    "<WiFi>",
+    "<WMT>",
+    "<STP>",
+    "<DBG>",
+    "<UNKOWN>"
+};
+
+
+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 {
+    int  id; /*type: 0. pkt trace 1. fw info 2. assert info 3. trace32 dump . -1. linked to the the previous*/
+    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
+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
+    CHAR info[STP_CORE_DUMP_INFO_SZ + 1];
+} WCN_CORE_DUMP_T, *P_WCN_CORE_DUMP_T;
+
+P_WCN_CORE_DUMP_T wcn_core_dump_init(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);
+extern INT32 wcn_core_dump_flush(INT32 rst);
+
+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(
+    char *  aucMsg,
+    unsigned char      cmd
+    );
+
+extern INT32 stp_dbg_aee_send(unsigned char *aucMsg, INT32 len, INT32 cmd);
+
+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);
+#endif /* end of _STP_DEBUG_H_ */
+
diff --git a/drivers/mtk_wcn_combo/common/linux/include/stp_sdio.h b/drivers/mtk_wcn_combo/common/linux/include/stp_sdio.h
new file mode 100755 (executable)
index 0000000..82f5118
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+** $Id: $
+*/
+
+/*! \file   "stp_sdio.h"
+    \brief
+
+
+*/
+
+/*
+** $Log: $
+*/
+
+#ifndef _STP_SDIO_H
+#define _STP_SDIO_H
+/*******************************************************************************
+*                         C O M P I L E R   F L A G S
+********************************************************************************
+*/
+
+
+#define KMALLOC_UPDATE 1
+
+#if 0 // NO support for multiple STP-SDIO instances (multiple MT6620) on a single host
+#define STP_SDIO_HOST_COUNT (1)
+#define STP_SDIO_ONLY_ONE_HOST (0)
+#endif
+#define STP_SDIO_POLL_OWNBACK_INTR (1)
+
+#define STP_SDIO_NEW_TXRING (0)
+/* George: Keep old (0) codes for debugging only!
+ * Use new code (1) for SQC and MP!
+ */
+
+#define STP_SDIO_OWN_THREAD (1)
+
+/*******************************************************************************
+*                    E X T E R N A L   R E F E R E N C E S
+********************************************************************************
+*/
+
+#include "osal.h"
+#include "hif_sdio.h"
+
+/*******************************************************************************
+*                              C O N S T A N T S
+********************************************************************************
+*/
+/* Common HIF register address */
+#define CCIR        (0x0000)
+#define CHLPCR        (0x0004)
+#define CSDIOCSR    (0x0008)
+#define CHCR        (0x000c)
+#define CHISR        (0x0010)
+#define CHIER        (0x0014)
+#define CTDR        (0x0018)
+#define CRDR        (0x001c)
+#define CTFSR        (0x0020)
+#define CRPLR        (0x0024)
+
+/* Common HIF register bit field address */
+/* CHLPCR */
+#define C_FW_OWN_REQ_CLR    (0x00000200)
+#define C_FW_OWN_REQ_SET    (0x00000100)
+#define C_FW_INT_EN_CLR     (0x00000002)
+#define C_FW_INT_EN_SET     (0x00000001)
+#define C_FW_COM_DRV_OWN    (0x00000100)
+
+/* CHIER */
+#define CHISR_EN_15_7       (0x0000ff80)
+#define CHISR_EN_3_0        (0x0000000f)
+/* CHISR */
+#define RX_PKT_LEN          (0xffff0000)
+#define FIRMWARE_INT        (0x0000fe00)
+#define TX_FIFO_OVERFLOW    (0x00000100)
+#define FW_INT_IND_INDICATOR (0x00000080)
+#define TX_COMPLETE_COUNT   (0x00000070)
+#define TX_UNDER_THOLD      (0x00000008)
+#define TX_EMPTY            (0x00000004)
+#define RX_DONE             (0x00000002)
+#define FW_OWN_BACK_INT     (0x00000001)
+
+/* hardware settings */
+#define STP_SDIO_TX_FIFO_SIZE (2080UL)
+#define STP_SDIO_RX_FIFO_SIZE (2304UL) /* 256*9 */
+#define STP_SDIO_TX_PKT_MAX_CNT (7) /* Max outstanding tx pkt count, as defined in TX_COMPLETE_COUNT */
+#define STP_SDIO_HDR_SIZE (4) /* hw,fw,sw follow the same format: 2 bytes length + 2 bytes reserved */
+
+/* sdio bus settings */
+#define STP_SDIO_BLK_SIZE (512UL)
+
+/* software driver settings */
+#define STP_SDIO_TX_BUF_CNT (16UL)/*(7)*/
+#define STP_SDIO_TX_BUF_CNT_MASK (STP_SDIO_TX_BUF_CNT - 1)
+#define STP_SDIO_TX_PKT_LIST_SIZE (STP_SDIO_TX_BUF_CNT) /* must be 2^x now... */
+#define STP_SDIO_TX_PKT_LIST_SIZE_MASK (STP_SDIO_TX_PKT_LIST_SIZE - 1)
+
+/* tx buffer size for a single entry */
+/* George: SHALL BE a multiple of the used BLK_SIZE!! */
+#if 1
+/* round up: 512*5 = 2560 > 2080 */
+#define STP_SDIO_TX_ENTRY_SIZE ((STP_SDIO_TX_FIFO_SIZE + (STP_SDIO_BLK_SIZE - 1)) & ~(STP_SDIO_BLK_SIZE - 1))
+#else
+/* round down: 512*4 = 2048 < 2080 */
+#define STP_SDIO_TX_MAX_BLK_CNT (STP_SDIO_TX_FIFO_SIZE / STP_SDIO_BLK_SIZE)
+#define STP_SDIO_TX_ENTRY_SIZE (STP_SDIO_TX_MAX_BLK_CNT * STP_SDIO_BLK_SIZE)
+#endif
+
+/*software rx buffer size */
+/*#define STP_SDIO_RX_BUF_SIZE (STP_SDIO_RX_FIFO_SIZE)*/
+/* George: SHALL BE a multiple of the used BLK_SIZE!! */
+#if 1
+/* round up: 512*5 = 2560 > 2304 */
+#define STP_SDIO_RX_BUF_SIZE ((STP_SDIO_RX_FIFO_SIZE + (STP_SDIO_BLK_SIZE - 1)) & ~(STP_SDIO_BLK_SIZE - 1))
+#else
+/* round down: 512*4 = 2048 < 2304 */
+#define STP_SDIO_RX_MAX_BLK_CNT (STP_SDIO_RX_FIFO_SIZE / STP_SDIO_BLK_SIZE)
+#define STP_SDIO_RX_BUF_SIZE (STP_SDIO_RX_MAX_BLK_CNT * STP_SDIO_BLK_SIZE)
+#endif
+
+
+/*******************************************************************************
+*                             D A T A   T Y P E S
+********************************************************************************
+*/
+/* HIF's local packet buffer variables for Tx/Rx */
+typedef struct _MTK_WCN_STP_SDIO_PKT_BUF {
+    /* Tx entry ring buffer. Entry size is aligned to SDIO block size. */
+#if KMALLOC_UPDATE
+    UINT8 *tx_buf;
+#else
+    UINT8 tx_buf[STP_SDIO_TX_BUF_CNT][STP_SDIO_TX_ENTRY_SIZE];    
+#endif
+    
+    /* Tx size ring buffer. Record valid data size in tx_buf. */
+    UINT32 tx_buf_sz[STP_SDIO_TX_BUF_CNT];
+    /* Tx debug timestamp: 1st time when the entry is filled with data */
+    UINT32 tx_buf_ts[STP_SDIO_TX_BUF_CNT];
+#if KMALLOC_UPDATE  
+    UINT8 *rx_buf;
+#else  
+    UINT8 rx_buf[STP_SDIO_RX_BUF_SIZE]; /* Rx buffer (not ring) */
+#endif    
+#if STP_SDIO_NEW_TXRING
+    UINT32 wr_cnt; /* Tx entry ring buffer write count */
+    UINT32 rd_cnt; /* Tx entry ring buffer read count */
+    spinlock_t rd_cnt_lock; /* Tx entry ring buffer read count spin lock */
+#else
+    UINT8 wr_idx; /* Tx ring buffer write index */ /*George: obsolete*/
+    UINT8 rd_idx; /* Tx ring buffer read index *//*George: obsolete*/
+    spinlock_t rd_idx_lock; /* spin lock for Tx ring buffer read index */
+#endif
+    MTK_WCN_BOOL full_flag; /* Tx entry ring buffer full flag (TRUE: full, FALSE: not full) */
+    /* save interrupt status flag for Tx entry ring buf spin lock */
+    unsigned long rd_irq_flag;
+    /* wait queue head for Tx entry ring buf full case */
+    wait_queue_head_t fullwait_q;
+} MTK_WCN_STP_SDIO_PKT_BUF;
+
+/* Tx packet list information */
+typedef struct _MTK_WCN_STP_SDIO_Tx_Pkt_LIST {
+    UINT32 pkt_rd_cnt;
+    UINT32 pkt_wr_cnt;
+    UINT16 pkt_size_list[STP_SDIO_TX_PKT_LIST_SIZE]; /*max length is FIFO Size */
+    UINT32 out_ts[STP_SDIO_TX_PKT_LIST_SIZE];
+    UINT32 in_ts[STP_SDIO_TX_PKT_LIST_SIZE];
+} MTK_WCN_STP_SDIO_Tx_Pkt_LIST;
+
+/* STP HIF firmware information */
+typedef struct _MTK_WCN_STP_SDIO_FIRMWARE_INFO {
+    UINT32 tx_fifo_size; /* Current left tx FIFO size */
+    UINT32 tx_packet_num; /* Current outstanding tx packet (0~7) */
+    atomic_t tx_comp_num; /* Current total tx ok but fifo size not released packet count */
+} MTK_WCN_STP_SDIO_FIRMWARE_INFO;
+
+/* STP SDIO private information */
+typedef struct _MTK_WCN_STP_SDIO_PRIVATE_INFO {
+    UINT8 stp_sdio_host_idx;
+} MTK_WCN_STP_SDIO_PRIVATE_INFO;
+
+/* STP SDIO host information */
+typedef struct _MTK_WCN_STP_SDIO_HIF_INFO {
+    MTK_WCN_HIF_SDIO_CLTCTX sdio_cltctx;
+    MTK_WCN_STP_SDIO_PKT_BUF pkt_buf;
+    MTK_WCN_STP_SDIO_Tx_Pkt_LIST tx_pkt_list;
+    UINT32 rx_pkt_len; /* George: use 32-bit for efficiency. Correct name to pkt for packet */
+    MTK_WCN_STP_SDIO_FIRMWARE_INFO firmware_info;
+    MTK_WCN_STP_SDIO_PRIVATE_INFO private_info;
+#if STP_SDIO_OWN_THREAD
+    //struct tasklet_struct tx_rx_job;
+    OSAL_THREAD tx_rx_thread;
+    INT32 irq_pending;
+    INT32 sleep_flag;
+    INT32 wakeup_flag;
+    INT32 awake_flag;
+    OSAL_EVENT tx_rx_event;
+    OSAL_SIGNAL isr_check_complete;
+#endif
+    struct work_struct tx_work;
+    struct work_struct rx_work;
+} MTK_WCN_STP_SDIO_HIF_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
+********************************************************************************
+*/
+/* STP_SDIO_TX_PKT_LIST_SIZE must be 2^x */
+#define STP_SDIO_GET_PKT_AR_IDX(idx) ((idx) & STP_SDIO_TX_PKT_LIST_SIZE_MASK)
+
+/*******************************************************************************
+*                   F U N C T I O N   D E C L A R A T I O N S
+********************************************************************************
+*/
+
+/*!
+ * \brief MTK hif sdio client registration function
+ *
+ * Client uses this function to do hif sdio registration
+ *
+ * \param pinfo     a pointer of client's information
+ *
+ * \retval 0    register successfully
+ * \retval < 0  error code
+ */
+extern INT32
+mtk_wcn_hif_sdio_client_reg (
+    const MTK_WCN_HIF_SDIO_CLTINFO *pinfo
+    );
+
+extern INT32
+mtk_wcn_stp_sdio_do_own_clr (void);
+
+//extern INT32
+//mtk_wcn_stp_sdio_do_own_set (void);
+
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+#endif /* _STP_SDIO_H */
+
diff --git a/drivers/mtk_wcn_combo/common/linux/include/wmt_dev.h b/drivers/mtk_wcn_combo/common/linux/include/wmt_dev.h
new file mode 100755 (executable)
index 0000000..81c17c7
--- /dev/null
@@ -0,0 +1,16 @@
+
+
+#ifndef _WMT_DEV_H_
+#define _WMT_DEV_H_
+
+
+#include "osal.h"
+
+extern VOID wmt_dev_rx_event_cb (VOID);
+extern INT32 wmt_dev_rx_timeout (P_OSAL_EVENT pEvent);
+extern INT32 wmt_dev_patch_get (UCHAR *pPatchName, osal_firmware **ppPatch,INT32 padSzBuf);
+extern INT32 wmt_dev_patch_put(osal_firmware **ppPatch);
+extern VOID wmt_dev_patch_info_free(VOID);
+
+
+#endif /*_WMT_DEV_H_*/
diff --git a/drivers/mtk_wcn_combo/common/linux/include/wmt_tm.h b/drivers/mtk_wcn_combo/common/linux/include/wmt_tm.h
new file mode 100755 (executable)
index 0000000..d1aeacc
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef _WMT_TM_H
+#define _WMT_TM_H
+#if WMT_PLAT_ALPS
+
+#define CONFIG_THERMAL_OPEN
+#if  defined(CONFIG_THERMAL) &&  defined(CONFIG_THERMAL_OPEN)
+
+       struct wmt_thermal_ctrl_ops {
+           int (*query_temp)(void);
+           int (*set_temp)(int);
+       };
+
+       int wmt_tm_init(struct wmt_thermal_ctrl_ops *ops);
+       int wmt_tm_deinit(void);
+       int wmt_tm_init_rt(void);
+       int wmt_tm_deinit_rt(void);
+#endif
+
+#endif
+#endif
diff --git a/drivers/mtk_wcn_combo/common/linux/osal.c b/drivers/mtk_wcn_combo/common/linux/osal.c
new file mode 100755 (executable)
index 0000000..ae93b43
--- /dev/null
@@ -0,0 +1,1297 @@
+/*! \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_ void osal_bug_on(unsigned long val)
+{
+       BUG_ON(val);
+}
+_osal_inline_ LONG osal_strtol(const char *str, char **c, UINT32 adecimal)
+{
+    return simple_strtol(str, c, adecimal);
+}
+
+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);*/// TODO: [FixMe][GeorgeKuo] BUG?
+    iRet = vsnprintf(buf, len, fmt, args);
+    va_end(args);
+
+    return iRet;
+}
+
+INT32 osal_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);
+
+    printk("%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);
+
+    printk(KERN_DEBUG "%s",tempString);
+
+    return 0;
+}
+
+
+INT32 osal_dbg_assert(INT32 expr, const char *file, INT32 line)
+{
+    if (!expr){
+        printk("%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);
+        printk("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);
+
+#if WMT_PLAT_ALPS
+    aee_kernel_warning(
+        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)
+{
+    return memcpy(dst, src, len);
+}
+
+
+_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 layer Thread Opeartion releated 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 releated 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 releated 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, PULONG 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, PULONG 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 = (ULONG)pTimer->timeroutHandlerData;
+    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 || pFifo->pFifoBody)
+    {
+        printk (KERN_ERR "pFifo must be !NULL, pFifo->pFifoBody must be NULL\n");
+        printk (KERN_ERR "pFifo(0x%p), pFifo->pFifoBody(0x%p)\n", pFifo, pFifo->pFifoBody);
+        return -1;
+    }
+
+    
+    #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35))
+            spin_lock_init(&pFifo->fifoSpinlock);
+            fifo = kfifo_alloc(size, /*GFP_KERNEL*/GFP_ATOMIC, &pFifo->fifoSpinlock);
+            if (NULL == fifo)
+            {
+                ret = -2;
+            }else
+            {
+                ret = 0;
+            }
+    #else
+        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;
+            }
+        } 
+    #endif
+    pFifo->pFifoBody = fifo;
+    return (ret < 0) ? (-1) : (0);
+}
+
+INT32 _osal_fifo_deinit(OSAL_FIFO *pFifo)
+{
+    struct kfifo *fifo = NULL;
+
+    if(!pFifo || !pFifo->pFifoBody)
+    {
+        printk("%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)
+    {
+        printk("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__);
+        return -1;
+    }
+
+    fifo = (struct kfifo *)pFifo->pFifoBody;
+
+    if(fifo)
+    {
+    #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35))
+        ret = fifo->size;
+    #else
+        ret = kfifo_size(fifo);
+    #endif
+    
+    }
+
+    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)
+    {
+        printk("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__);
+        return -1;
+    }
+
+    fifo = (struct kfifo *)pFifo->pFifoBody;
+
+    if(fifo)
+    {
+    #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35))
+        ret = fifo->size - kfifo_len(fifo);
+    #else
+        ret = kfifo_avail(fifo);
+    #endif
+    }
+
+    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)
+    {
+        printk("%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)
+    {
+        printk("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__);
+        return -1;
+    }
+
+    fifo = (struct kfifo *)pFifo->pFifoBody;
+
+    if(fifo)
+    {
+    #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35))
+        ret = (fifo->in == fifo->out);
+    #else
+        ret = kfifo_is_empty(fifo);
+    #endif
+    }
+
+    return ret;
+}
+
+INT32 _osal_fifo_is_full(OSAL_FIFO *pFifo)
+{
+    struct kfifo *fifo = NULL;
+    INT32  ret = 0;
+
+    if(!pFifo || !pFifo->pFifoBody)
+    {
+        printk("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__);
+        return -1;
+    }
+
+    fifo = (struct kfifo *)pFifo->pFifoBody;
+
+    if(fifo)
+    {
+    #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35))
+        ret = (fifo->size == _osal_fifo_len(pFifo));
+    #else
+        ret = kfifo_is_full(fifo);
+    #endif
+    }
+
+    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)
+    {
+        printk("%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)))
+    {       
+    #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
+        ret = kfifo_put(fifo, buf, len);
+    #else
+        ret = kfifo_in(fifo, buf, len);
+    #endif
+        
+    }
+    else
+    {
+        printk("%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)
+    {
+        printk("%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)))
+    {
+    #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
+        ret = kfifo_get(fifo, buf, len);
+    #else
+        ret = kfifo_out(fifo, buf, len);
+    #endif
+    }
+    else
+    {
+        printk("%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)
+    {
+        printk("%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)
+    {
+        printk("%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)
+    {
+        printk("%s:Becasue 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
+    {
+        printk("%s:pFifo = NULL, error\n", __func__);
+    }
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35))
+    
+#else
+
+    if(pFifo->pFifoBody)
+    {
+        kfree(pFifo->pFifoBody);
+    }
+#endif
+}
+
+INT32 osal_fifo_reset(P_OSAL_FIFO pFifo)
+{
+    if(pFifo)
+    {
+        return pFifo->FifoReset(pFifo);
+    }
+    else
+    {
+        printk("%s:pFifo = NULL, error\n", __func__);
+        return -1;
+    }
+}
+
+UINT32 osal_fifo_in(P_OSAL_FIFO pFifo, PUINT8 buffer, UINT32 size)
+{
+    if(pFifo)
+    {
+        return pFifo->FifoDataIn(pFifo, buffer, size);
+    }
+    else 
+    {   
+        printk("%s:pFifo = NULL, error\n", __func__);
+        return 0;
+    }
+}
+
+UINT32 osal_fifo_out(P_OSAL_FIFO pFifo, PUINT8 buffer, UINT32 size)
+{
+    if(pFifo)
+    {
+        return pFifo->FifoDataOut(pFifo, buffer, size);    
+    }
+    else
+    {
+        printk("%s:pFifo = NULL, error\n", __func__);
+        return 0;
+    }
+}
+
+UINT32 osal_fifo_len(P_OSAL_FIFO pFifo)
+{
+    if(pFifo)
+    {
+        return pFifo->FifoLen(pFifo);
+    }
+    else 
+    {
+        printk("%s:pFifo = NULL, error\n", __func__);
+        return 0;
+    }
+}
+
+UINT32 osal_fifo_sz(P_OSAL_FIFO pFifo)
+{
+    if(pFifo)
+    {
+        return pFifo->FifoSz(pFifo);
+    }
+    else 
+    {
+        printk("%s:pFifo = NULL, error\n", __func__);
+        return 0;
+    }
+}
+
+UINT32 osal_fifo_avail(P_OSAL_FIFO pFifo)
+{
+    if(pFifo)
+    {
+        return pFifo->FifoAvailSz(pFifo);
+    }
+    else 
+    {
+        printk("%s:pFifo = NULL, error\n", __func__);
+        return 0;
+    }
+}
+
+UINT32 osal_fifo_is_empty(P_OSAL_FIFO pFifo)
+{
+    if(pFifo)
+    {
+        return pFifo->FifoIsEmpty(pFifo);
+    }
+    else 
+    {
+        printk("%s:pFifo = NULL, error\n", __func__);
+        return 0;
+    }
+}
+
+UINT32 osal_fifo_is_full(P_OSAL_FIFO pFifo)
+{
+    if(pFifo)
+    {
+        return pFifo->FifoIsFull(pFifo);
+    }
+    else 
+    {
+        printk("%s:pFifo = NULL, error\n", __func__);
+        return 0;
+    }
+}
+
+INT32  osal_wake_lock_init(P_OSAL_WAKE_LOCK pLock)
+{
+    if(!pLock)
+    {
+        return -1;
+    } 
+    else 
+    {
+        wake_lock_init(&pLock->wake_lock, WAKE_LOCK_SUSPEND, pLock->name);
+        
+        return 0;
+    }
+}
+
+INT32  osal_wake_lock(P_OSAL_WAKE_LOCK pLock)
+{
+    if(!pLock)
+    {
+        return -1;
+    }
+    else
+    {
+        wake_lock(&pLock->wake_lock);
+
+        return 0;
+    }
+}
+
+
+INT32  osal_wake_unlock(P_OSAL_WAKE_LOCK pLock)
+{
+    if(!pLock)
+    {
+        return -1;
+    }
+    else
+    {
+        wake_unlock(&pLock->wake_lock);
+
+        return 0;
+    }
+}
+
+INT32  osal_wake_lock_count(P_OSAL_WAKE_LOCK pLock)
+{
+    INT32 count = 0;
+
+    if(!pLock)
+    {
+        return -1;
+    }
+    else 
+    {
+        count = wake_lock_active(&pLock->wake_lock);    
+        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;
+}
+
+extern 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_msleep(UINT32 ms)
+{
+    msleep(ms);
+    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;
+
+    printk("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))  printk("\n");
+        printk("0x%02x ",  buf[k]);
+    }
+    printk("<end of dump\n");
+}
+
+UINT32 osal_op_get_id(P_OSAL_OP pOp) 
+{
+    return (pOp) ? pOp->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);
+    }
+}
+
diff --git a/drivers/mtk_wcn_combo/common/linux/stp_chrdev_bt.c b/drivers/mtk_wcn_combo/common/linux/stp_chrdev_bt.c
new file mode 100755 (executable)
index 0000000..17037da
--- /dev/null
@@ -0,0 +1,514 @@
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/sched.h>
+#include <asm/current.h>
+#include <asm/uaccess.h>
+#include <linux/fcntl.h>
+#include <linux/poll.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+#include "stp_exp.h"
+#include "wmt_exp.h"
+
+MODULE_LICENSE("Dual BSD/GPL");
+
+#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_BT_HWVER           6
+
+#define COMBO_IOC_MAGIC        0xb0
+#define COMBO_IOCTL_FW_ASSERT  _IOWR(COMBO_IOC_MAGIC, 0, void*)
+
+unsigned int gDbgLevel = BT_LOG_INFO;
+
+#define BT_DBG_FUNC(fmt, arg...)    if(gDbgLevel >= BT_LOG_DBG){ printk(PFX "%s: "  fmt, __FUNCTION__ ,##arg);}
+#define BT_INFO_FUNC(fmt, arg...)   if(gDbgLevel >= BT_LOG_INFO){ printk(PFX "%s: "  fmt, __FUNCTION__ ,##arg);}
+#define BT_WARN_FUNC(fmt, arg...)   if(gDbgLevel >= BT_LOG_WARN){ printk(PFX "%s: "  fmt, __FUNCTION__ ,##arg);}
+#define BT_ERR_FUNC(fmt, arg...)    if(gDbgLevel >= BT_LOG_ERR){ printk(PFX "%s: "   fmt, __FUNCTION__ ,##arg);}
+#define BT_TRC_FUNC(f)              if(gDbgLevel >= BT_LOG_DBG){printk(PFX "<%s> <%d>\n", __FUNCTION__, __LINE__);}
+
+#define VERSION "1.0"
+#define BT_NVRAM_CUSTOM_NAME "/data/BT_Addr"
+
+static int BT_devs = 1;        /* device count */
+static int BT_major = BT_DEV_MAJOR;       /* dynamic allocation */
+module_param(BT_major, uint, 0);
+static struct cdev BT_cdev;
+
+static unsigned char i_buf[MTKSTP_BUFFER_SIZE];    // input buffer of read()
+static unsigned char o_buf[MTKSTP_BUFFER_SIZE];    // output buffer of write()
+static struct semaphore wr_mtx, rd_mtx;
+static wait_queue_head_t inq;    /* read queues */
+static DECLARE_WAIT_QUEUE_HEAD(BT_wq);
+static int flag = 0;
+volatile int retflag = 0;
+
+unsigned char g_bt_bd_addr[10]={0x01,0x1a,0xfc,0x06,0x00,0x55,0x66,0x77,0x88,0x00};
+unsigned char g_nvram_btdata[8];
+
+static int nvram_read(char *filename, char *buf, ssize_t len, int offset)
+{
+    struct file *fd;
+    //ssize_t ret;
+    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)) {
+        BT_ERR_FUNC("failed to open!!\n");
+        return -1;
+    }
+    do{
+        if ((fd->f_op == NULL) || (fd->f_op->read == NULL))
+            {
+            BT_ERR_FUNC("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) {
+                        BT_ERR_FUNC("[nvram_read] : failed to seek!!\n");
+                        break;
+                    }
+              } else {
+                    fd->f_pos = offset;
+              }
+        }
+
+            retLen = fd->f_op->read(fd,
+                                          buf,
+                                          len,
+                                          &fd->f_pos);
+
+    }while(false);
+
+    filp_close(fd, NULL);
+
+    set_fs(old_fs);
+
+    return retLen;
+}
+
+
+int platform_load_nvram_data( char * filename, char * buf, int len)
+{
+    //int ret;
+    BT_INFO_FUNC("platform_load_nvram_data ++ BDADDR\n");
+
+    return nvram_read( filename, buf, len, 0);
+}
+
+static void bt_cdev_rst_cb(
+    ENUM_WMTDRV_TYPE_T src,
+    ENUM_WMTDRV_TYPE_T dst,
+    ENUM_WMTMSG_TYPE_T type,
+    void *buf,
+    unsigned int sz){
+
+    /*
+        To handle reset procedure please
+    */
+    ENUM_WMTRSTMSG_TYPE_T rst_msg;
+
+    BT_INFO_FUNC("sizeof(ENUM_WMTRSTMSG_TYPE_T) = %d\n", sizeof(ENUM_WMTRSTMSG_TYPE_T));
+    if(sz <= sizeof(ENUM_WMTRSTMSG_TYPE_T)){
+        memcpy((char *)&rst_msg, (char *)buf, sz);
+        BT_INFO_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 restart start!\n");
+                        retflag = 1;
+                        wake_up_interruptible(&inq);
+                        /*reset_start message handling*/
+
+                    } else if(rst_msg == WMTRSTMSG_RESET_END){
+                        BT_INFO_FUNC("BT restart end!\n");
+                        retflag = 2;
+                        wake_up_interruptible(&inq);
+                        /*reset_end message handling*/
+                    }
+        }
+    } else {
+        /*message format invalid*/
+    BT_INFO_FUNC("message format invalid!\n");
+    }
+}
+
+void BT_event_cb(void)
+{
+    BT_DBG_FUNC("BT_event_cb() \n");
+
+    flag = 1;
+    wake_up(&BT_wq);
+
+    /* finally, awake any reader */
+    wake_up_interruptible(&inq);  /* blocked in read() and select() */
+
+    return;
+}
+
+unsigned int BT_poll(struct file *filp, poll_table *wait)
+{
+    unsigned int 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);
+
+        /* empty let select sleep */
+        if((!mtk_wcn_stp_is_rxqueue_empty(BT_TASK_INDX)) || retflag)
+        {
+            mask |= POLLIN | POLLRDNORM;  /* readable */
+        }
+    }
+    else
+    {
+        mask |= POLLIN | POLLRDNORM;  /* readable */
+    }
+
+    /* do we need condition? */
+    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)
+{
+    int retval = 0;
+    int written = 0;
+    down(&wr_mtx);
+
+    BT_DBG_FUNC("%s: count %d pos %lld\n", __func__, count, *f_pos);
+    if(retflag)
+    {
+        if (retflag == 1) //reset start
+        {
+            retval = -88;
+            BT_INFO_FUNC("MT662x reset Write: start\n");
+        }
+        else if (retflag == 2) // reset end
+        {
+          retval = -99;
+            BT_INFO_FUNC("MT662x reset Write: end\n");
+        }
+    goto OUT;
+    }
+
+    if (count > 0)
+    {
+        int copy_size = (count < MTKSTP_BUFFER_SIZE) ? count : MTKSTP_BUFFER_SIZE;
+        if (copy_from_user(&o_buf[0], &buf[0], copy_size))
+        {
+            retval = -EFAULT;
+            goto OUT;
+        }
+        //printk("%02x ", val);
+
+        written = mtk_wcn_stp_send_data(&o_buf[0], copy_size, BT_TASK_INDX);
+        if(0 == written)
+        {
+            retval = -ENOSPC;
+            /*no windowspace in STP is available, native process should not call BT_write with no delay at all*/
+            BT_ERR_FUNC("target packet length:%d, write success length:%d, retval = %d.\n", count, written, retval);
+        }
+        else
+        {
+            retval = written;
+        }
+
+    }else
+    {
+        retval = -EFAULT;
+        BT_ERR_FUNC("target packet length:%d 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)
+{
+    int retval = 0;
+
+    down(&rd_mtx);
+
+    BT_DBG_FUNC("BT_read(): count %d pos %lld\n", count, *f_pos);
+    if(retflag)
+    {
+        if (retflag == 1) //reset start
+        {
+            retval = -88;
+            BT_INFO_FUNC("MT662x reset Read: start\n");
+        }
+        else if (retflag == 2) // reset end
+        {
+            retval = -99;
+            BT_INFO_FUNC("MT662x reset Read: end\n");
+        }
+    goto OUT;
+    }
+
+    if(count > MTKSTP_BUFFER_SIZE)
+    {
+        count = MTKSTP_BUFFER_SIZE;
+    }
+    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("BT_read(): wait_event 1\n");
+        wait_event(BT_wq, flag != 0);
+        BT_DBG_FUNC("BT_read(): wait_event 2\n");
+        flag = 0;
+        retval = mtk_wcn_stp_receive_data(i_buf, count, BT_TASK_INDX);
+        BT_DBG_FUNC("BT_read(): mtk_wcn_stp_receive_data() = %d\n", retval);
+    }
+
+    // we got something from STP driver
+    if (copy_to_user(buf, i_buf, retval))
+    {
+        retval = -EFAULT;
+        goto OUT;
+    }
+
+OUT:
+    up(&rd_mtx);
+    BT_DBG_FUNC("BT_read(): retval = %d\n", 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)
+{
+    int retval = 0;
+    MTK_WCN_BOOL bRet = MTK_WCN_BOOL_TRUE;
+
+    ENUM_WMTHWVER_TYPE_T hw_ver_sym = WMTHWVER_INVALID;
+    BT_DBG_FUNC("BT_ioctl(): cmd (%d)\n", cmd);
+
+    switch(cmd)
+    {
+#if 0
+        case 0: // enable/disable STP
+            /* George: STP is controlled by WMT only */
+            /* mtk_wcn_stp_enable(arg); */
+            break;
+#endif
+        case 1: // send raw data
+            BT_DBG_FUNC("BT_ioctl(): disable raw data from BT dev \n");
+            retval = -EINVAL;
+            break;
+        case COMBO_IOC_BT_HWVER:
+            /*get combo hw version*/
+            hw_ver_sym = mtk_wcn_wmt_hwver_get();
+
+            BT_INFO_FUNC("BT_ioctl(): get hw version = %d, sizeof(hw_ver_sym) = %d\n", 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:
+            /* BT trigger fw assert for debug*/
+            BT_INFO_FUNC("BT Set fw assert......\n");
+            bRet = mtk_wcn_wmt_assert();
+            if (bRet == MTK_WCN_BOOL_TRUE) {
+                BT_INFO_FUNC("BT Set fw assert OK\n");
+                retval = 0;
+            } else {
+                BT_INFO_FUNC("BT Set fw assert Failed\n");
+                retval = (-1000);
+            }
+            break;
+            
+        default:
+            retval = -EFAULT;
+            BT_DBG_FUNC("BT_ioctl(): unknown cmd (%d)\n", cmd);
+            break;
+    }
+
+    return retval;
+}
+
+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
+        );
+       if(current->pid ==1)
+               return 0;
+#if 1 /* GeorgeKuo: turn on function before check stp ready */
+     /* 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;
+    }else{
+        retflag = 0;
+        mtk_wcn_wmt_msgcb_reg(WMTDRV_TYPE_BT, bt_cdev_rst_cb);
+        BT_INFO_FUNC("WMT register BT rst cb!\n");
+    }
+#endif
+
+    if (mtk_wcn_stp_is_ready()) {
+#if 0 /* GeorgeKuo: turn on function before check stp ready */
+         /* 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;
+        }
+#endif
+        mtk_wcn_stp_set_bluez(0);
+
+        BT_INFO_FUNC("Now it's in MTK Bluetooth Mode\n");
+        BT_INFO_FUNC("WMT turn on BT OK!\n");
+        BT_INFO_FUNC("STP is ready!\n");
+        platform_load_nvram_data(BT_NVRAM_CUSTOM_NAME,
+            (char *)&g_nvram_btdata, sizeof(g_nvram_btdata));
+
+        BT_INFO_FUNC("Read NVRAM : BD address %02x%02x%02x%02x%02x%02x Cap 0x%02x Codec 0x%02x\n",
+            g_nvram_btdata[0], g_nvram_btdata[1], g_nvram_btdata[2],
+            g_nvram_btdata[3], g_nvram_btdata[4], g_nvram_btdata[5],
+            g_nvram_btdata[6], g_nvram_btdata[7]);
+
+        mtk_wcn_stp_register_event_cb(BT_TASK_INDX, BT_event_cb);
+               BT_INFO_FUNC("mtk_wcn_stp_register_event_cb finish\n");
+    }
+    else {
+        BT_ERR_FUNC("STP is not ready\n");
+
+        /*return error code*/
+        return -ENODEV;
+    }
+
+//    init_MUTEX(&wr_mtx);
+    sema_init(&wr_mtx, 1);
+//    init_MUTEX(&rd_mtx);
+    sema_init(&rd_mtx, 1);
+       BT_INFO_FUNC("finish\n");
+
+    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
+        );
+       if(current->pid ==1)
+               return 0;
+    retflag = 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_INFO_FUNC("WMT turn off BT fail!\n");
+        return -EIO;    //mostly, native programmer will not check this return value.
+    }
+    else {
+        BT_INFO_FUNC("WMT turn off BT OK!\n");
+    }
+
+    return 0;
+}
+
+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,
+    .poll = BT_poll
+};
+
+static int BT_init(void)
+{
+    dev_t dev = MKDEV(BT_major, 0);
+    int alloc_ret = 0;
+    int cdev_err = 0;
+
+    /*static allocate chrdev*/
+    alloc_ret = register_chrdev_region(dev, 1, BT_DRIVER_NAME);
+    if (alloc_ret) {
+        BT_ERR_FUNC("fail to register chrdev\n");
+        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;
+
+    BT_INFO_FUNC("%s driver(major %d) installed.\n", BT_DRIVER_NAME, BT_major);
+    retflag = 0;
+    mtk_wcn_stp_register_event_cb(BT_TASK_INDX, NULL);
+
+    /* init wait queue */
+    init_waitqueue_head(&(inq));
+
+    return 0;
+
+error:
+    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);
+    retflag = 0;
+    mtk_wcn_stp_register_event_cb(BT_TASK_INDX, NULL);  // unregister event callback function
+
+    cdev_del(&BT_cdev);
+    unregister_chrdev_region(dev, BT_devs);
+
+    BT_INFO_FUNC("%s driver removed.\n", BT_DRIVER_NAME);
+}
+
+module_init(BT_init);
+module_exit(BT_exit);
+
+
diff --git a/drivers/mtk_wcn_combo/common/linux/stp_chrdev_gps.c b/drivers/mtk_wcn_combo/common/linux/stp_chrdev_gps.c
new file mode 100755 (executable)
index 0000000..755cd56
--- /dev/null
@@ -0,0 +1,427 @@
+/** $Log: stp_chrdev_gps.c $
+ *
+ * 12 13 2010 Sean.Wang
+ * (1) Add GPS_DEBUG_TRACE_GPIO to disable GPIO debugging trace
+ * (2) Add GPS_DEBUG_DUMP to support GPS data dump
+ * (3) Add mtk_wcn_stp_is_ready() check in GPS_open()
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/sched.h>
+#include <asm/current.h>
+#include <asm/uaccess.h>
+#include <linux/skbuff.h>
+
+#include "stp_exp.h"
+#include "wmt_exp.h"
+
+MODULE_LICENSE("GPL");
+
+#define GPS_DRIVER_NAME "mtk_stp_GPS_chrdev"
+#define GPS_DEV_MAJOR 191 // never used number
+#define GPS_DEBUG_TRACE_GPIO         0
+#define GPS_DEBUG_DUMP               0
+
+#define PFX                         "[GPS] "
+#define GPS_LOG_DBG                  3
+#define GPS_LOG_INFO                 2
+#define GPS_LOG_WARN                 1
+#define GPS_LOG_ERR                  0
+
+#define COMBO_IOC_GPS_HWVER           6
+
+unsigned int gDbgLevel = GPS_LOG_DBG;
+
+#define GPS_DBG_FUNC(fmt, arg...)    if(gDbgLevel >= GPS_LOG_DBG){ printk(PFX "%s: "  fmt, __FUNCTION__ ,##arg);}
+#define GPS_INFO_FUNC(fmt, arg...)   if(gDbgLevel >= GPS_LOG_INFO){ printk(PFX "%s: "  fmt, __FUNCTION__ ,##arg);}
+#define GPS_WARN_FUNC(fmt, arg...)   if(gDbgLevel >= GPS_LOG_WARN){ printk(PFX "%s: "  fmt, __FUNCTION__ ,##arg);}
+#define GPS_ERR_FUNC(fmt, arg...)    if(gDbgLevel >= GPS_LOG_ERR){ printk(PFX "%s: "  fmt, __FUNCTION__ ,##arg);}
+#define GPS_TRC_FUNC(f)              if(gDbgLevel >= GPS_LOG_DBG){ printk(PFX "<%s> <%d>\n", __FUNCTION__, __LINE__);}
+
+
+static int GPS_devs = 1;        /* device count */
+static int GPS_major = GPS_DEV_MAJOR;       /* dynamic allocation */
+module_param(GPS_major, uint, 0);
+static struct cdev GPS_cdev;
+
+static unsigned char i_buf[MTKSTP_BUFFER_SIZE];    // input buffer of read()
+static unsigned char o_buf[MTKSTP_BUFFER_SIZE];    // output buffer of write()
+static struct semaphore wr_mtx, rd_mtx;
+static DECLARE_WAIT_QUEUE_HEAD(GPS_wq);
+static int flag = 0;
+
+static void GPS_event_cb(void);
+
+ssize_t GPS_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
+{
+    int retval = 0;
+    int written = 0;
+    down(&wr_mtx);
+
+    //GPS_TRC_FUNC();
+
+    /*printk("%s: count %d pos %lld\n", __func__, count, *f_pos);*/
+    if (count > 0)
+    {
+        int copy_size = (count < MTKSTP_BUFFER_SIZE) ? count : MTKSTP_BUFFER_SIZE;
+        if (copy_from_user(&o_buf[0], &buf[0], copy_size))
+        {
+            retval = -EFAULT;
+            goto out;
+        }
+        //printk("%02x ", val);
+#if GPS_DEBUG_TRACE_GPIO        
+        mtk_wcn_stp_debug_gpio_assert(IDX_GPS_TX, DBG_TIE_LOW);
+#endif
+        written = mtk_wcn_stp_send_data(&o_buf[0], copy_size, GPS_TASK_INDX);
+#if GPS_DEBUG_TRACE_GPIO
+        mtk_wcn_stp_debug_gpio_assert(IDX_GPS_TX, DBG_TIE_HIGH);
+#endif
+
+#if GPS_DEBUG_DUMP
+{            
+    unsigned char *buf_ptr = &o_buf[0];            
+    int k=0;            
+    printk("--[GPS-WRITE]--");            
+    for(k=0; k < 10 ; k++){  
+    if(k%16 == 0)  printk("\n");                
+        printk("0x%02x ", o_buf[k]);            
+    }            
+    printk("\n");        
+}
+#endif
+        /*
+            If cannot send successfully, enqueue again
+        
+        if (written != copy_size) {
+            // George: FIXME! Move GPS retry handling from app to driver 
+        }
+        */
+        if(0 == written)
+        {
+            retval = -ENOSPC;
+            /*no windowspace in STP is available, native process should not call GPS_write with no delay at all*/
+            GPS_ERR_FUNC("target packet length:%d, write success length:%d, retval = %d.\n", count, written, retval);
+        }
+        else
+        {
+            retval = written;
+        }
+    }
+    else
+    {
+        retval = -EFAULT;
+        GPS_ERR_FUNC("target packet length:%d is not allowed, retval = %d.\n", count, retval);
+    }
+out:
+    up(&wr_mtx);
+    return (retval);
+}
+
+ssize_t GPS_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
+{
+    long val = 0;
+    int retval;
+
+    down(&rd_mtx);
+
+/*    printk("GPS_read(): count %d pos %lld\n", count, *f_pos);*/
+
+    if(count > MTKSTP_BUFFER_SIZE)
+    {
+        count = MTKSTP_BUFFER_SIZE;
+    }
+    
+#if GPS_DEBUG_TRACE_GPIO    
+    mtk_wcn_stp_debug_gpio_assert(IDX_GPS_RX, DBG_TIE_LOW);
+#endif
+    retval = mtk_wcn_stp_receive_data(i_buf, count, GPS_TASK_INDX);
+#if GPS_DEBUG_TRACE_GPIO
+    mtk_wcn_stp_debug_gpio_assert(IDX_GPS_RX, DBG_TIE_HIGH);
+#endif
+
+    while(retval == 0) // got nothing, wait for STP's signal
+    {
+        /*wait_event(GPS_wq, flag != 0);*/ /* George: let signal wake up */
+        val = wait_event_interruptible(GPS_wq, flag != 0);
+        flag = 0;
+            
+#if GPS_DEBUG_TRACE_GPIO
+        mtk_wcn_stp_debug_gpio_assert(IDX_GPS_RX, DBG_TIE_LOW);
+#endif
+
+        retval = mtk_wcn_stp_receive_data(i_buf, count, GPS_TASK_INDX);
+
+#if GPS_DEBUG_TRACE_GPIO
+        mtk_wcn_stp_debug_gpio_assert(IDX_GPS_RX, DBG_TIE_HIGH);
+#endif
+        /* if we are signaled */
+        if (val) {
+            if (-ERESTARTSYS == val) {
+                GPS_INFO_FUNC("signaled by -ERESTARTSYS(%ld) \n ", val);
+            }
+            else {
+                GPS_INFO_FUNC("signaled by %ld \n ", val);
+            }
+            break;
+        }
+    }
+
+#if GPS_DEBUG_DUMP    
+{   
+    unsigned char *buf_ptr = &i_buf[0];        
+    int k=0;        
+    printk("--[GPS-READ]--");       
+    for(k=0; k < 10 ; k++){       
+    if(k%16 == 0)  printk("\n");            
+    printk("0x%02x ", i_buf[k]);        
+    }        
+    printk("--\n");    
+}
+#endif
+
+    if (retval) {
+    // we got something from STP driver
+        if (copy_to_user(buf, i_buf, retval)) {
+        retval = -EFAULT;
+        goto OUT;
+        }
+        else {
+            /* success */
+        }
+    }
+    else {
+        // we got nothing from STP driver, being signaled
+        retval = val;
+    }
+
+OUT:
+    up(&rd_mtx);
+/*    printk("GPS_read(): retval = %d\n", retval);*/
+    return (retval);
+}
+
+//int GPS_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
+long GPS_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+    int retval = 0;
+    ENUM_WMTHWVER_TYPE_T hw_ver_sym = WMTHWVER_INVALID;
+
+    printk("GPS_ioctl(): cmd (%d)\n", cmd);
+
+    switch(cmd)
+    {
+        case 0: // enable/disable STP
+            GPS_INFO_FUNC(KERN_INFO "GPS_ioctl(): disable STP control from GPS dev\n");
+            retval = -EINVAL;
+#if 1
+#else
+             /* George: STP is controlled by WMT only */
+            mtk_wcn_stp_enable(arg);
+#endif
+            break;
+
+        case 1: // send raw data
+            GPS_INFO_FUNC(KERN_INFO "GPS_ioctl(): disable raw data from GPS dev \n");
+            retval = -EINVAL;
+            break;
+
+        case COMBO_IOC_GPS_HWVER:             
+            /*get combo hw version*/            
+            hw_ver_sym = mtk_wcn_wmt_hwver_get();
+
+            GPS_INFO_FUNC(KERN_INFO "GPS_ioctl(): get hw version = %d, sizeof(hw_ver_sym) = %d\n", hw_ver_sym, sizeof(hw_ver_sym));
+            if(copy_to_user((int __user *)arg, &hw_ver_sym, sizeof(hw_ver_sym))){
+               retval = -EFAULT;
+            }
+            break;
+            
+        default:
+            retval = -EFAULT;
+            GPS_INFO_FUNC(KERN_INFO "GPS_ioctl(): unknown cmd (%d)\n", cmd);
+            break;
+    }
+
+/*OUT:*/
+    return retval;
+}
+
+static void gps_cdev_rst_cb(
+    ENUM_WMTDRV_TYPE_T src, 
+    ENUM_WMTDRV_TYPE_T dst, 
+    ENUM_WMTMSG_TYPE_T type, 
+    void *buf, 
+    unsigned int sz){
+
+    /*
+        To handle reset procedure please
+    */
+    ENUM_WMTRSTMSG_TYPE_T rst_msg;
+
+    GPS_INFO_FUNC("sizeof(ENUM_WMTRSTMSG_TYPE_T) = %d\n", sizeof(ENUM_WMTRSTMSG_TYPE_T));
+    if(sz <= sizeof(ENUM_WMTRSTMSG_TYPE_T)){ 
+        memcpy((char *)&rst_msg, (char *)buf, sz);
+        GPS_INFO_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_GPS) &&
+                (type == WMTMSG_TYPE_RESET)){                
+                    if(rst_msg == WMTRSTMSG_RESET_START){
+                        GPS_INFO_FUNC("gps restart start!\n");
+
+                        /*reset_start message handling*/
+                        
+                    } else if(rst_msg == WMTRSTMSG_RESET_END){
+                        GPS_INFO_FUNC("gps restart end!\n");
+
+                        /*reset_end message handling*/
+                    }
+        }
+    } else {
+        /*message format invalid*/
+    }
+}
+
+static int GPS_open(struct inode *inode, struct file *file)
+{
+    printk("%s: major %d minor %d (pid %d)\n", __func__,
+        imajor(inode),
+        iminor(inode),
+        current->pid
+        );
+       if(current->pid ==1)
+                       return 0;
+
+#if 1 /* GeorgeKuo: turn on function before check stp ready */
+     /* turn on BT */
+
+    if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_GPS)) {
+        GPS_WARN_FUNC("WMT turn on GPS fail!\n");
+        return -ENODEV;
+    } else {
+        mtk_wcn_wmt_msgcb_reg(WMTDRV_TYPE_GPS, gps_cdev_rst_cb);
+        GPS_INFO_FUNC("WMT turn on GPS OK!\n");
+    }
+#endif
+
+    if (mtk_wcn_stp_is_ready()) {
+#if 0
+        if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_GPS)) {
+            GPS_WARN_FUNC("WMT turn on GPS fail!\n");
+            return -ENODEV;
+        }
+        GPS_INFO_FUNC("WMT turn on GPS OK!\n");
+#endif
+        mtk_wcn_stp_register_event_cb(GPS_TASK_INDX, GPS_event_cb);
+    }  else {        
+        GPS_ERR_FUNC("STP is not ready, Cannot open GPS Devices\n\r");
+        
+        /*return error code*/
+        return -ENODEV;
+    }
+
+    //init_MUTEX(&wr_mtx);
+    sema_init(&wr_mtx, 1);
+    //init_MUTEX(&rd_mtx);
+    sema_init(&rd_mtx, 1);
+    
+    return 0;
+}
+
+static int GPS_close(struct inode *inode, struct file *file)
+{
+    printk("%s: major %d minor %d (pid %d)\n", __func__,
+        imajor(inode),
+        iminor(inode),
+        current->pid
+        );
+       if(current->pid ==1)
+                       return 0;
+
+    /*Flush Rx Queue*/
+    mtk_wcn_stp_register_event_cb(GPS_TASK_INDX, 0x0);  // unregister event callback function
+    mtk_wcn_wmt_msgcb_unreg(WMTDRV_TYPE_GPS);
+    
+    if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_off(WMTDRV_TYPE_GPS)) {
+        GPS_WARN_FUNC("WMT turn off GPS fail!\n");
+        return -EIO;    //mostly, native programer does not care this return vlaue, but we still return error code.
+    }
+    else {       
+        GPS_INFO_FUNC("WMT turn off GPS OK!\n");
+    }
+
+    return 0;
+}
+
+struct file_operations GPS_fops = {
+    .open = GPS_open,
+    .release = GPS_close,
+    .read = GPS_read,
+    .write = GPS_write,
+//    .ioctl = GPS_ioctl
+    .unlocked_ioctl = GPS_unlocked_ioctl,
+};
+
+void GPS_event_cb(void)
+{
+/*    printk("GPS_event_cb() \n");*/
+
+    flag = 1;
+    wake_up(&GPS_wq);
+
+    return;
+}
+
+static int GPS_init(void)
+{
+    dev_t dev = MKDEV(GPS_major, 0);
+    int alloc_ret = 0;
+    int cdev_err = 0;
+
+    /*static allocate chrdev*/
+    alloc_ret = register_chrdev_region(dev, 1, GPS_DRIVER_NAME);
+    if (alloc_ret) {
+        printk("fail to register chrdev\n");
+        return alloc_ret;
+    }
+
+    cdev_init(&GPS_cdev, &GPS_fops);
+    GPS_cdev.owner = THIS_MODULE;
+
+    cdev_err = cdev_add(&GPS_cdev, dev, GPS_devs);
+    if (cdev_err)
+        goto error;
+
+    printk(KERN_ALERT "%s driver(major %d) installed.\n", GPS_DRIVER_NAME, GPS_major);
+    
+    return 0;
+
+error:
+    if (cdev_err == 0)
+        cdev_del(&GPS_cdev);
+
+    if (alloc_ret == 0)
+        unregister_chrdev_region(dev, GPS_devs);
+
+    return -1;
+}
+
+static void GPS_exit(void)
+{
+    dev_t dev = MKDEV(GPS_major, 0);
+
+    cdev_del(&GPS_cdev);
+    unregister_chrdev_region(dev, GPS_devs);
+
+    printk(KERN_ALERT "%s driver removed.\n", GPS_DRIVER_NAME);
+}
+
+module_init(GPS_init);
+module_exit(GPS_exit);
+
+EXPORT_SYMBOL(GPS_event_cb);
+
diff --git a/drivers/mtk_wcn_combo/common/linux/stp_dbg.c b/drivers/mtk_wcn_combo/common/linux/stp_dbg.c
new file mode 100755 (executable)
index 0000000..771a4fa
--- /dev/null
@@ -0,0 +1,1294 @@
+#include <linux/kernel.h> // GFP_KERNEL
+#include <linux/timer.h>  //init_timer, add_time, del_timer_sync
+#include <linux/time.h>  //gettimeofday
+#include <linux/delay.h>
+#include <linux/slab.h> //kzalloc
+#include <linux/sched.h> //task's status
+#include <linux/vmalloc.h>
+#include <linux/err.h>
+#include <linux/workqueue.h>
+#include <asm/atomic.h>
+
+#include <net/sock.h>
+#include <net/netlink.h>
+#include <linux/skbuff.h>
+#include <net/genetlink.h>
+
+#include <linux/zlib.h>
+#include <linux/uaccess.h>
+#include <linux/crc32.h>
+
+#include "stp_dbg.h"
+//#include "stp_btm.h"
+#include "btm_core.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...)   if(gStpDbgDbgLevel >= STP_DBG_LOG_LOUD){  printk(KERN_DEBUG PFX_STP_DBG "%s: "  fmt, __FUNCTION__ ,##arg);}
+#define STP_DBG_DBG_FUNC(fmt, arg...)    if(gStpDbgDbgLevel >= STP_DBG_LOG_DBG){  printk(KERN_DEBUG PFX_STP_DBG "%s: "  fmt, __FUNCTION__ ,##arg);}
+#define STP_DBG_INFO_FUNC(fmt, arg...)   if(gStpDbgDbgLevel >= STP_DBG_LOG_INFO){ printk(PFX_STP_DBG "%s: "  fmt, __FUNCTION__ ,##arg);}
+#define STP_DBG_WARN_FUNC(fmt, arg...)   if(gStpDbgDbgLevel >= STP_DBG_LOG_WARN){ printk(PFX_STP_DBG "%s: "  fmt, __FUNCTION__ ,##arg);}
+#define STP_DBG_ERR_FUNC(fmt, arg...)    if(gStpDbgDbgLevel >= STP_DBG_LOG_ERR){  printk(PFX_STP_DBG "%s: "   fmt, __FUNCTION__ ,##arg);}
+#define STP_DBG_TRC_FUNC(f)              if(gStpDbgDbgLevel >= STP_DBG_LOG_DBG){  printk(KERN_DEBUG PFX_STP_DBG "<%s> <%d>\n", __FUNCTION__, __LINE__);}
+
+
+MTKSTP_DBG_T *g_stp_dbg = NULL;
+
+#define STP_DBG_FAMILY_NAME        "STP_DBG"
+#define MAX_BIND_PROCESS    (4)
+
+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 */
+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,
+};
+
+static unsigned int stp_dbg_seqnum = 0;
+static int num_bind_process = 0;
+static pid_t bind_pid[MAX_BIND_PROCESS];
+
+static P_WCN_CORE_DUMP_T g_core_dump = NULL;
+
+/* core_dump_timeout_handler - handler of coredump timeout
+ * @ data - core dump object's pointer
+ * 
+ * No return value
+ */
+static void core_dump_timeout_handler(ULONG data)
+{
+    P_WCN_CORE_DUMP_T dmp = (P_WCN_CORE_DUMP_T)data;
+    
+    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 timeout)
+{
+    #define KBYTES (1024*sizeof(char))
+    #define L1_BUF_SIZE (32*KBYTES) 
+    #define L2_BUF_SIZE (512*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, L2_BUF_SIZE);
+    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 = (ULONG)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);
+    }
+
+    osal_sleepable_lock_deinit(&core_dmp->dmp_lock);
+    
+    return NULL;
+}
+
+
+/* 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;
+}
+
+
+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 "MT6628 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);
+            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 WMT_PLAT_ALPS
+            aee_kernel_dal_show("MT662x coredump start, please wait up to 5 minutes.\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, 1);
+            } 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, 1);
+            } 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);
+
+    return 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)
+{
+    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%08x, len %d\n", (unsigned int)pbuf, len);
+            
+    // show coredump end info on UI
+    //osal_dbg_assert_aee("MT662x f/w coredump end", "MT662x firmware coredump ends");
+    #if WMT_PLAT_ALPS
+    aee_kernel_dal_show("MT662x coredump end\n");
+       
+    // call AEE driver API
+    aed_combo_exception(NULL, 0, (const int*)pbuf, len, (const char*)g_core_dump->info);
+    #endif
+    // 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("in buf 0x%08x, in sz %d\n", (unsigned int)in_buf, in_sz);
+    STP_DBG_INFO_FUNC("out buf 0x%08x, out sz %d\n", (unsigned int)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;
+             } else {
+                           STP_DBG_ERR_FUNC("finish operation failed %d\n", val);
+                           return -3;
+            }
+               }                       
+        }
+
+               *out_sz = tmp - stream->avail_out;
+       }
+
+    STP_DBG_INFO_FUNC("out buf 0x%08x, out sz %d\n", (unsigned int)out_buf, *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 (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%08x, len %d\n", (unsigned int)*pbuf, *plen);
+    
+#if 1
+    ret = zlib_deflateReset((z_stream*)cprs->worker);
+    if (ret != Z_OK) {
+        STP_DBG_ERR_FUNC("reset failed!\n");
+        return -2;
+    }
+#endif
+
+    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;
+
+    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;
+    printk(" %s-len:%d\n", title, len);
+    //printk("    ", title, len);
+    for(k=0; k < len ; k++){
+        if(k%16 == 0 && k != 0)  printk("\n    ");
+        printk("0x%02x ",  pBuf[k]);
+    }
+    printk("--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;
+    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)
+        {
+            STP_DBG_HDR_T *pHdr = NULL;
+            char* pBuf = NULL;
+            unsigned int len =0;
+            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);
+            len = stp_dbg->logsys->queue[stp_dbg->logsys->in].len - sizeof (STP_DBG_HDR_T);
+            printk("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);
+            }
+            
+        }
+        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;
+        printk ("STP-DBG: enable pkt log dump out.\n");
+    }
+    else
+    {
+        gStpDbgLogOut = 0;
+        printk ("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;
+        printk("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;
+    } else {
+        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;
+
+    osal_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 {
+        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(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__);
+        }
+    }
+
+    return;
+}
+
+static void stp_dbg_nl_deinit(void)
+{
+    genl_unregister_family(&stp_dbg_gnl_family);
+    return;
+}
+
+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_pid;
+        num_bind_process++;
+        STP_DBG_INFO_FUNC("%s():-> pid  = %d\n", __func__, info->snd_pid);
+    }
+    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;
+}
+
+char
+stp_dbg_nl_send(
+    char *  aucMsg,
+    unsigned char      cmd
+    )
+{
+    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_string(skb, STP_DBG_ATTR_MSG, aucMsg);
+            if(rc != 0) 
+            {            
+                nlmsg_free(skb);
+                STP_DBG_ERR_FUNC("%s(): nla_put_string fail...\n", __func__);
+                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);
+    }
+
+    return ret;
+}
+
+
+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(IS_ERR(stp_dbg)){
+        STP_DBG_ERR_FUNC("-ENOMEM\n");
+        goto ERR_EXIT1;
+    }
+
+    stp_dbg->logsys = vmalloc(sizeof(MTKSTP_LOG_SYS_T));
+    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_TIMEOUT);
+    
+    return stp_dbg;
+
+ERR_EXIT2:
+    kfree(stp_dbg);
+    return NULL;
+
+ERR_EXIT1:
+    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);
+    
+    //unbind with netlink
+    stp_dbg_nl_deinit();
+
+    if(stp_dbg->logsys){
+        vfree(stp_dbg->logsys);
+    }
+
+    if(stp_dbg){
+        kfree(stp_dbg);
+    }
+
+    return 0;
+}
+
+
+
+
+
+
+
diff --git a/drivers/mtk_wcn_combo/common/linux/stp_uart.c b/drivers/mtk_wcn_combo/common/linux/stp_uart.c
new file mode 100755 (executable)
index 0000000..0e5b634
--- /dev/null
@@ -0,0 +1,938 @@
+#include <linux/version.h>
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/poll.h>
+
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/signal.h>
+#include <linux/ioctl.h>
+#include <linux/skbuff.h>
+
+#include <linux/spinlock.h>
+
+#include <linux/time.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/kfifo.h>
+
+
+#include "stp_exp.h"
+
+#define N_MTKSTP              (15 + 1) /* refer to linux tty.h use N_HCI. */
+
+#define HCIUARTSETPROTO        _IOW('U', 200, int)
+
+#define MAX(a,b)        ((a) > (b) ? (a) : (b))
+#define MIN(a,b)        ((a) < (b) ? (a) : (b))
+
+#define PFX                         "[UART] "
+#define UART_LOG_LOUD                 4
+#define UART_LOG_DBG                  3
+#define UART_LOG_INFO                 2
+#define UART_LOG_WARN                 1
+#define UART_LOG_ERR                  0
+
+#define MAX_PACKET_ALLOWED                2000
+
+
+unsigned int gDbgLevel = UART_LOG_INFO;
+
+#define UART_DBG_FUNC(fmt, arg...)    if(gDbgLevel >= UART_LOG_DBG){  printk(KERN_DEBUG PFX "%s: "  fmt, __FUNCTION__ ,##arg);}
+#define UART_INFO_FUNC(fmt, arg...)   if(gDbgLevel >= UART_LOG_INFO){ printk(PFX "%s: "  fmt, __FUNCTION__ ,##arg);}
+#define UART_WARN_FUNC(fmt, arg...)   if(gDbgLevel >= UART_LOG_WARN){ printk(PFX "%s: "  fmt, __FUNCTION__ ,##arg);}
+#define UART_ERR_FUNC(fmt, arg...)    if(gDbgLevel >= UART_LOG_ERR){  printk(PFX "%s: "   fmt, __FUNCTION__ ,##arg);}
+#define UART_TRC_FUNC(f)              if(gDbgLevel >= UART_LOG_DBG){  printk(KERN_DEBUG PFX "<%s> <%d>\n", __FUNCTION__, __LINE__);}
+
+
+#include <linux/kfifo.h>
+#define LDISC_RX_TASKLET  0
+#define LDISC_RX_WORK  1
+
+#if WMT_UART_RX_MODE_WORK
+#define LDISC_RX LDISC_RX_WORK
+#else
+#define LDISC_RX LDISC_RX_TASKLET
+#endif
+
+#if (LDISC_RX == LDISC_RX_TASKLET)
+#define LDISC_RX_FIFO_SIZE (0x20000) /*8192 bytes*/
+struct kfifo *g_stp_uart_rx_fifo = NULL;
+spinlock_t    g_stp_uart_rx_fifo_spinlock;
+struct tasklet_struct g_stp_uart_rx_fifo_tasklet;
+#define RX_BUFFER_LEN 1024
+unsigned char g_rx_data[RX_BUFFER_LEN];
+
+//static DEFINE_RWLOCK(g_stp_uart_rx_handling_lock);
+#elif (LDISC_RX == LDISC_RX_WORK)
+
+#define LDISC_RX_FIFO_SIZE (0x4000) /* 16K bytes shall be enough...... */
+#define LDISC_RX_BUF_SIZE (2048) /* 2K bytes in one shot is enough */
+
+UINT8 *g_stp_uart_rx_buf; /* for stp rx data parsing */
+struct kfifo *g_stp_uart_rx_fifo = NULL; /* for uart tty data receiving */
+spinlock_t g_stp_uart_rx_fifo_spinlock; /* fifo spinlock */
+struct workqueue_struct *g_stp_uart_rx_wq; /* rx work queue (do not use system_wq) */
+struct work_struct *g_stp_uart_rx_work; /* rx work */
+
+#endif
+
+struct tty_struct *stp_tty = 0x0;
+
+unsigned char tx_buf[MTKSTP_BUFFER_SIZE] = {0x0};
+int rd_idx = 0;
+int wr_idx = 0;
+//struct semaphore buf_mtx;
+spinlock_t         buf_lock;
+static INT32  mtk_wcn_uart_tx(const UINT8 *data, const UINT32 size, UINT32 *written_size);
+
+
+static inline int stp_uart_tx_wakeup(struct tty_struct *tty)
+{
+    int len = 0;
+    int written = 0;
+    int written_count = 0;
+    static int i = 0;
+    //unsigned long flags;
+    // get data from ring buffer
+//    down(&buf_mtx);
+    UART_DBG_FUNC("++\n");
+////    spin_lock_irqsave(&buf_lock, flags);
+
+#if 0
+    if((i > 1000) && (i % 5)== 0)
+    {
+        UART_INFO_FUNC("i=(%d), ****** drop data from uart******\n", i);
+        i++;
+        return 0;
+    } else {
+
+        UART_INFO_FUNC("i=(%d)at stp uart **\n", i);
+    }
+#endif
+
+    len = (wr_idx >= rd_idx) ? (wr_idx - rd_idx) : (MTKSTP_BUFFER_SIZE - rd_idx);
+    if(len > 0 && len < MAX_PACKET_ALLOWED)
+    {
+        i++;
+        /*
+         *     ops->write is called by the kernel to write a series of
+         *     characters to the tty device.  The characters may come from
+         *     user space or kernel space.  This routine will return the
+         *    number of characters actually accepted for writing.
+        */
+        set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+        written = tty->ops->write(tty, &tx_buf[rd_idx], len);
+        if(written != len) {
+           UART_ERR_FUNC("Error(i-%d):[pid(%d)(%s)]tty-ops->write FAIL!len(%d)wr(%d)wr_i(%d)rd_i(%d)\n\r", i, current->pid, current->comm, len, written, wr_idx, rd_idx);
+           return -1;
+        }
+        written_count = written;
+        //printk("len = %d, written = %d\n", len, written);
+        rd_idx = ((rd_idx + written) % MTKSTP_BUFFER_SIZE);
+        // all data is accepted by UART driver, check again in case roll over
+            len = (wr_idx >= rd_idx) ? (wr_idx - rd_idx) : (MTKSTP_BUFFER_SIZE - rd_idx);
+            if(len > 0 && len < MAX_PACKET_ALLOWED)
+            {
+                set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+                written = tty->ops->write(tty, &tx_buf[rd_idx], len);
+                if (written != len)
+                {
+                    UART_ERR_FUNC("Error(i-%d):[pid(%d)(%s)]len(%d)wr(%d)wr_i(%d)rd_i(%d)\n\r", i, current->pid, current->comm, len, written, wr_idx, rd_idx);
+                    return -1;
+                }
+                rd_idx = ((rd_idx + written) % MTKSTP_BUFFER_SIZE);
+                written_count += written;
+            }
+            else if(len < 0 || len >= MAX_PACKET_ALLOWED)
+            {
+                UART_ERR_FUNC("Warnning(i-%d):[pid(%d)(%s)]length verfication(external) warnning,len(%d), wr_idx(%d), rd_idx(%d)!\n\r", i, current->pid, current->comm, len, wr_idx, rd_idx);
+                return -1;
+            }
+    }
+    else
+    {
+        UART_ERR_FUNC("Warnning(i-%d):[pid(%d)(%s)]length verfication(external) warnning,len(%d), wr_idx(%d), rd_idx(%d)!\n\r", i, current->pid, current->comm, len, wr_idx, rd_idx);
+        return -1;
+    }
+    //up(&buf_mtx);
+////    spin_unlock_irqrestore(&buf_lock, flags);
+    UART_DBG_FUNC("--\n");
+    return written_count;
+}
+
+/* ------ LDISC part ------ */
+/* stp_uart_tty_open
+ *
+ *     Called when line discipline changed to HCI_UART.
+ *
+ * Arguments:
+ *     tty    pointer to tty info structure
+ * Return Value:
+ *     0 if success, otherwise error code
+ */
+static int stp_uart_tty_open(struct tty_struct *tty)
+{
+    UART_DBG_FUNC("stp_uart_tty_opentty: %p\n", tty);
+
+    tty->receive_room = 65536;
+    tty->low_latency = 1;
+
+    /* Flush any pending characters in the driver and line discipline. */
+
+    /* FIXME: why is this needed. Note don't use ldisc_ref here as the
+       open path is before the ldisc is referencable */
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
+    /* definition changed!! */
+    if (tty->ldisc->ops->flush_buffer) {
+        tty->ldisc->ops->flush_buffer(tty);
+    }
+#else
+    if (tty->ldisc.ops->flush_buffer) {
+        tty->ldisc.ops->flush_buffer(tty);
+    }
+#endif
+
+    tty_driver_flush_buffer(tty);
+
+//    init_MUTEX(&buf_mtx);
+////    spin_lock_init(&buf_lock);
+
+    rd_idx = wr_idx = 0;
+    stp_tty = tty;
+    mtk_wcn_stp_register_if_tx(STP_UART_IF_TX,  mtk_wcn_uart_tx);
+
+    return 0;
+}
+
+/* stp_uart_tty_close()
+ *
+ *    Called when the line discipline is changed to something
+ *    else, the tty is closed, or the tty detects a hangup.
+ */
+static void stp_uart_tty_close(struct tty_struct *tty)
+{
+    UART_DBG_FUNC("stp_uart_tty_close(): tty %p\n", tty);
+    mtk_wcn_stp_register_if_tx(STP_UART_IF_TX, NULL);
+
+    return;
+}
+
+/* stp_uart_tty_wakeup()
+ *
+ *    Callback for transmit wakeup. Called when low level
+ *    device driver can accept more send data.
+ *
+ * Arguments:        tty    pointer to associated tty instance data
+ * Return Value:    None
+ */
+static void stp_uart_tty_wakeup(struct tty_struct *tty)
+{
+    //printk("%s: start !!\n", __FUNCTION__);
+
+    //clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+
+    //stp_uart_tx_wakeup(tty);
+
+    return;
+}
+
+/* stp_uart_tty_receive()
+ *
+ *     Called by tty low level driver when receive data is
+ *     available.
+ *
+ * Arguments:  tty          pointer to tty isntance data
+ *             data         pointer to received data
+ *             flags        pointer to flags for data
+ *             count        count of received data in bytes
+ *
+ * Return Value:    None
+ */
+#if  (LDISC_RX  == LDISC_RX_TASKLET)
+
+static int stp_uart_fifo_init(void)
+{
+    int err = 0;
+    /*add rx fifo*/
+        #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35))
+        {
+        spin_lock_init(&g_stp_uart_rx_fifo_spinlock);
+        g_stp_uart_rx_fifo = kfifo_alloc(LDISC_RX_FIFO_SIZE, GFP_ATOMIC, &g_stp_uart_rx_fifo_spinlock);
+        if (NULL == g_stp_uart_rx_fifo)
+        {
+            UART_ERR_FUNC("kfifo_alloc failed (kernel version < 2.6.35)\n");
+            err = -1;
+        }
+        }
+        #else
+        {
+            g_stp_uart_rx_fifo = kzalloc(sizeof(struct kfifo), GFP_ATOMIC);
+            if (NULL == g_stp_uart_rx_fifo)
+            {
+                err = -2;
+                UART_ERR_FUNC("kzalloc for g_stp_uart_rx_fifo failed (kernel version > 2.6.35)\n");
+            }
+            err = kfifo_alloc(g_stp_uart_rx_fifo, LDISC_RX_FIFO_SIZE, GFP_ATOMIC);
+            if (0 != err)
+            {
+                UART_ERR_FUNC("kfifo_alloc failed, errno(%d)(kernel version > 2.6.35)\n", err);
+                kfree(g_stp_uart_rx_fifo);
+                g_stp_uart_rx_fifo = NULL;
+                err = -3;    
+            }
+        }
+        #endif
+    if (0 == err)
+    {
+        if (NULL != g_stp_uart_rx_fifo)
+        {
+            kfifo_reset(g_stp_uart_rx_fifo);
+            UART_ERR_FUNC("stp_uart_fifo_init() success.\n");
+        }
+        else
+        {
+            err = -4;
+            UART_ERR_FUNC("abnormal case, err = 0 but g_stp_uart_rx_fifo = NULL, set err to %d\n", err);
+        }
+    }
+    else
+    {
+        UART_ERR_FUNC("stp_uart_fifo_init() failed.\n");
+    }
+    return err;
+}
+
+static int stp_uart_fifo_deinit(void)
+{
+    if (NULL != g_stp_uart_rx_fifo)
+    {
+        kfifo_free(g_stp_uart_rx_fifo);
+        #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35))
+                //do nothing
+        #else
+            kfree(g_stp_uart_rx_fifo);
+        #endif
+        g_stp_uart_rx_fifo = NULL;
+    }    
+    return 0;
+}
+
+static void stp_uart_rx_handling(unsigned long func_data){
+    unsigned int how_much_get = 0;
+    unsigned int how_much_to_get = 0;
+    unsigned int flag = 0;
+    
+//    read_lock(&g_stp_uart_rx_handling_lock);
+    how_much_to_get = kfifo_len(g_stp_uart_rx_fifo);
+    
+    if (how_much_to_get >= RX_BUFFER_LEN)
+    {
+        flag = 1;
+        UART_INFO_FUNC ("fifolen(%d)\n", how_much_to_get);
+    }
+    
+    do{
+        #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35))
+        how_much_get= kfifo_get(g_stp_uart_rx_fifo, g_rx_data, RX_BUFFER_LEN);
+        #else
+        how_much_get= kfifo_out(g_stp_uart_rx_fifo, g_rx_data, RX_BUFFER_LEN);
+        #endif
+        //UART_INFO_FUNC ("fifoget(%d)\n", how_much_get);
+        mtk_wcn_stp_parser_data((UINT8 *)g_rx_data, how_much_get);
+        how_much_to_get = kfifo_len(g_stp_uart_rx_fifo);
+    }while(how_much_to_get > 0);
+    
+//    read_unlock(&g_stp_uart_rx_handling_lock);
+    if (1 == flag)
+    {
+        UART_INFO_FUNC ("finish, fifolen(%d)\n", kfifo_len(g_stp_uart_rx_fifo));
+    }
+}
+
+static void stp_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *flags, int count)
+{
+    unsigned int fifo_avail_len = LDISC_RX_FIFO_SIZE - kfifo_len(g_stp_uart_rx_fifo);
+    unsigned int how_much_put = 0;
+#if 0
+    {
+        struct timeval now;
+        do_gettimeofday(&now);
+        printk("[+STP][  ][R] %4d --> sec = %lu, --> usec --> %lu\n",
+            count, now.tv_sec, now.tv_usec);
+    }
+#endif
+//    write_lock(&g_stp_uart_rx_handling_lock);
+    if(count > 2000){
+        /*this is abnormal*/
+        UART_ERR_FUNC("abnormal: buffer count = %d\n", count);
+    }
+    /*How much empty seat?*/
+    if(fifo_avail_len > 0){
+    //UART_INFO_FUNC ("fifo left(%d), count(%d)\n", fifo_avail_len, count);
+        #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35))
+        how_much_put = kfifo_put(g_stp_uart_rx_fifo,(unsigned char *) data, count);
+            #else
+            how_much_put = kfifo_in(g_stp_uart_rx_fifo,(unsigned char *) data, count);
+            #endif
+
+        /*schedule it!*/
+        tasklet_schedule(&g_stp_uart_rx_fifo_tasklet);
+    }else{
+        UART_ERR_FUNC("stp_uart_tty_receive rxfifo is full!!\n");
+    }
+
+#if 0
+    {
+        struct timeval now;
+        do_gettimeofday(&now);
+        printk("[-STP][  ][R] %4d --> sec = %lu, --> usec --> %lu\n",
+            count, now.tv_sec, now.tv_usec);
+    }
+#endif
+
+//    write_unlock(&g_stp_uart_rx_handling_lock);
+
+}
+#elif  (LDISC_RX  ==LDISC_RX_WORK)
+static int stp_uart_fifo_init(void)
+{
+    int err = 0;
+
+    #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+    g_stp_uart_rx_buf = vzalloc(LDISC_RX_BUF_SIZE);
+    if (!g_stp_uart_rx_buf) {
+        UART_ERR_FUNC("kfifo_alloc failed (kernel version >= 2.6.37)\n");
+        err = -4;
+        goto fifo_init_end;
+    }
+    #else
+    g_stp_uart_rx_buf = vmalloc(LDISC_RX_BUF_SIZE);
+    if (!g_stp_uart_rx_buf) {
+        UART_ERR_FUNC("kfifo_alloc failed (kernel version < 2.6.37)\n");
+        err = -4;
+        goto fifo_init_end;
+    }
+    memset(g_stp_uart_rx_buf, 0, LDISC_RX_BUF_SIZE);
+    #endif
+
+    UART_INFO_FUNC("g_stp_uart_rx_buf alloc ok(0x%p, %d)\n",
+        g_stp_uart_rx_buf, LDISC_RX_BUF_SIZE);
+
+    /*add rx fifo*/
+    #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
+    spin_lock_init(&g_stp_uart_rx_fifo_spinlock);
+    g_stp_uart_rx_fifo = kfifo_alloc(LDISC_RX_FIFO_SIZE, GFP_KERNEL, &g_stp_uart_rx_fifo_spinlock);
+    if (NULL == g_stp_uart_rx_fifo) {
+        UART_ERR_FUNC("kfifo_alloc failed (kernel version < 2.6.33)\n");
+        err = -1;
+        goto fifo_init_end;
+    }
+    #else
+    /* allocate struct kfifo first */
+    g_stp_uart_rx_fifo = kzalloc(sizeof(struct kfifo), GFP_KERNEL);
+    if (NULL == g_stp_uart_rx_fifo) {
+        err = -2;
+        UART_ERR_FUNC("kzalloc struct kfifo failed (kernel version > 2.6.33)\n");
+        goto fifo_init_end;
+    }
+
+    /* allocate kfifo data buffer then */
+    err = kfifo_alloc(g_stp_uart_rx_fifo, LDISC_RX_FIFO_SIZE, GFP_KERNEL);
+    if (0 != err) {
+        UART_ERR_FUNC("kfifo_alloc failed, err(%d)(kernel version > 2.6.33)\n", err);
+        kfree(g_stp_uart_rx_fifo);
+        g_stp_uart_rx_fifo = NULL;
+        err = -3;
+        goto fifo_init_end;
+    }
+    #endif
+    UART_INFO_FUNC("g_stp_uart_rx_fifo alloc ok\n");
+
+fifo_init_end:
+
+    if (0 == err) {
+        /* kfifo init ok */
+        kfifo_reset(g_stp_uart_rx_fifo);
+        UART_DBG_FUNC("g_stp_uart_rx_fifo init success\n");
+    }
+    else {
+        UART_ERR_FUNC("stp_uart_fifo_init() fail(%d)\n", err);
+        if (g_stp_uart_rx_buf) {
+            UART_ERR_FUNC("free g_stp_uart_rx_buf\n");
+            vfree(g_stp_uart_rx_buf);
+            g_stp_uart_rx_buf = NULL;
+        }
+    }
+
+    return err;
+}
+
+static int stp_uart_fifo_deinit(void)
+{
+    if (g_stp_uart_rx_buf) {
+        vfree(g_stp_uart_rx_buf);
+        g_stp_uart_rx_buf = NULL;
+    }
+
+    if (NULL != g_stp_uart_rx_fifo) {
+        kfifo_free(g_stp_uart_rx_fifo);
+        #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
+        //do nothing
+        #else
+        kfree(g_stp_uart_rx_fifo);
+        #endif
+        g_stp_uart_rx_fifo = NULL;
+    }
+    return 0;
+}
+
+static void stp_uart_fifo_reset (void) {
+    if (NULL != g_stp_uart_rx_fifo) {
+        kfifo_reset(g_stp_uart_rx_fifo);
+    }
+}
+
+static void stp_uart_rx_worker (struct work_struct *work)
+{
+    unsigned int read;
+
+    if (unlikely(!g_stp_uart_rx_fifo)) {
+        UART_ERR_FUNC("NULL rx fifo!\n");
+        return;
+    }
+    if (unlikely(!g_stp_uart_rx_buf)) {
+        UART_ERR_FUNC("NULL rx buf!\n");
+        return;
+    }
+       
+
+    /* run until fifo becomes empty */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
+    while (kfifo_len(g_stp_uart_rx_fifo)) {
+        read = kfifo_get(g_stp_uart_rx_fifo, g_stp_uart_rx_buf, LDISC_RX_BUF_SIZE);
+        //UART_LOUD_FUNC("kfifo_get(%d)\n", read);
+        if (likely(read)) {
+            mtk_wcn_stp_parser_data((UINT8 *)g_stp_uart_rx_buf, read);
+        }
+    }
+#else
+    while (!kfifo_is_empty(g_stp_uart_rx_fifo)) {
+        read = kfifo_out(g_stp_uart_rx_fifo, g_stp_uart_rx_buf, LDISC_RX_BUF_SIZE);
+        UART_DBG_FUNC("kfifo_out(%d)\n", read);
+               //printk("rx_work:%d\n\r",read);
+        if (likely(read)) {
+            //UART_LOUD_FUNC("->%d\n", read);
+            mtk_wcn_stp_parser_data((UINT8 *)g_stp_uart_rx_buf, read);
+            //UART_LOUD_FUNC("<-\n", read);
+        }
+    }
+#endif
+
+    return;
+}
+
+/* stp_uart_tty_receive()
+ *
+ *     Called by tty low level driver when receive data is
+ *     available.
+ *
+ * Arguments:  tty          pointer to tty isntance data
+ *             data         pointer to received data
+ *             flags        pointer to flags for data
+ *             count        count of received data in bytes
+ *
+ * Return Value:    None
+ */
+static void stp_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *flags, int count)
+{
+    unsigned int written;
+
+    //UART_LOUD_FUNC("URX:%d\n", count);
+    if (unlikely(count > 2000)) {
+        UART_WARN_FUNC("abnormal: buffer count = %d\n", count);
+    }
+
+    if (unlikely(!g_stp_uart_rx_fifo || !g_stp_uart_rx_work || !g_stp_uart_rx_wq)) {
+        UART_ERR_FUNC("abnormal g_stp_uart_rx_fifo(0x%p),g_stp_uart_rx_work(0x%p),g_stp_uart_rx_wq(0x%p)\n",
+            g_stp_uart_rx_fifo, g_stp_uart_rx_work, g_stp_uart_rx_wq);
+        return;
+    }
+
+    /* need to check available buffer size? skip! */
+
+    /* need to lock fifo? skip for single writer single reader! */
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
+    written = kfifo_put(g_stp_uart_rx_fifo, (unsigned char *) data, count);
+#else
+    written = kfifo_in(g_stp_uart_rx_fifo, (unsigned char *) data, count);
+#endif
+       //printk("uart_rx:%d,wr:%d\n\r",count,written);
+
+    queue_work(g_stp_uart_rx_wq, g_stp_uart_rx_work);
+
+    if (unlikely(written != count)) {
+        UART_ERR_FUNC("c(%d),w(%d) bytes dropped\n", count, written);
+    }
+
+    return;
+}
+
+#else
+
+static void stp_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *flags, int count)
+{
+
+#if 0
+    mtk_wcn_stp_debug_gpio_assert(IDX_STP_RX_PROC, DBG_TIE_LOW);
+#endif
+
+    if(count > 2000){
+        /*this is abnormal*/
+        UART_ERR_FUNC("stp_uart_tty_receive buffer count = %d\n", count);
+    }
+
+#if 0
+    {
+        struct timeval now;
+
+        do_gettimeofday(&now);
+
+        printk("[+STP][  ][R] %4d --> sec = %d, --> usec --> %d\n",
+            count, now.tv_sec, now.tv_usec);
+    }
+#endif
+
+
+    /*There are multi-context to access here? Need to spinlock?*/
+    /*Only one context: flush_to_ldisc in tty_buffer.c*/
+    mtk_wcn_stp_parser_data((UINT8 *)data, (UINT32)count);
+
+#if 0
+    mtk_wcn_stp_debug_gpio_assert(IDX_STP_RX_PROC, DBG_TIE_HIGH);
+#endif
+
+    tty_unthrottle(tty);
+
+#if 0
+    {
+        struct timeval now;
+
+        do_gettimeofday(&now);
+
+        printk("[-STP][  ][R] %4d --> sec = %d, --> usec --> %d\n",
+            count, now.tv_sec, now.tv_usec);
+    }
+#endif
+    return;
+}
+#endif
+
+/* stp_uart_tty_ioctl()
+ *
+ *    Process IOCTL system call for the tty device.
+ *
+ * Arguments:
+ *
+ *    tty        pointer to tty instance data
+ *    file       pointer to open file object for device
+ *    cmd        IOCTL command code
+ *    arg        argument for IOCTL call (cmd dependent)
+ *
+ * Return Value:    Command dependent
+ */
+static int stp_uart_tty_ioctl(struct tty_struct *tty, struct file * file,
+                    unsigned int cmd, unsigned long arg)
+{
+    int err = 0;
+
+    UART_DBG_FUNC("%s =>\n", __FUNCTION__);
+
+    switch (cmd) {
+    case HCIUARTSETPROTO:
+            UART_DBG_FUNC("<!!> Set low_latency to TRUE <!!>\n");
+            tty->low_latency = 1;
+        break;
+    default:
+        UART_DBG_FUNC("<!!> n_tty_ioctl_helper <!!>\n");
+        err = n_tty_ioctl_helper(tty, file, cmd, arg);
+        break;
+    };
+    UART_DBG_FUNC("%s <=\n", __FUNCTION__);
+
+    return err;
+}
+
+/*
+ * We don't provide read/write/poll interface for user space.
+ */
+static ssize_t stp_uart_tty_read(struct tty_struct *tty, struct file *file,
+                    unsigned char __user *buf, size_t nr)
+{
+    return 0;
+}
+
+static ssize_t stp_uart_tty_write(struct tty_struct *tty, struct file *file,
+                    const unsigned char *data, size_t count)
+{
+    return 0;
+}
+
+static unsigned int stp_uart_tty_poll(struct tty_struct *tty,
+                    struct file *filp, poll_table *wait)
+{
+    return 0;
+}
+
+INT32  mtk_wcn_uart_tx(const UINT8 *data, const UINT32 size, UINT32 *written_size)
+{
+    int room;
+    //int idx = 0;
+    //unsigned long flags;
+    unsigned int  len;
+    //static int tmp=0;
+    static int i = 0;
+    if(stp_tty == NULL) return -1;
+    UART_DBG_FUNC("++\n");
+    (*written_size) = 0;
+
+    // put data into ring buffer
+    //down(&buf_mtx);
+
+
+    /*
+        [PatchNeed]
+        spin_lock_irqsave is redundant
+    */
+    //spin_lock_irqsave(&buf_lock, flags);
+
+    room = (wr_idx >= rd_idx) ? (MTKSTP_BUFFER_SIZE - (wr_idx - rd_idx) - 1) : (rd_idx - wr_idx - 1);
+    UART_DBG_FUNC("r(%d)s(%d)wr_i(%d)rd_i(%d)\n\r", room, size, wr_idx, rd_idx);
+    /*
+        [PatchNeed]
+        Block copy instead of byte copying
+    */
+    if(data == NULL){
+        UART_ERR_FUNC("pid(%d)(%s): data is NULL\n", current->pid, current->comm);
+        (*written_size) = 0;
+        UART_DBG_FUNC("--\n");
+        return -2;
+    }
+
+    #if 1
+    if(unlikely(size > room)){
+        UART_ERR_FUNC("pid(%d)(%s)room is not available, size needed(%d), wr_idx(%d), rd_idx(%d), room left(%d)\n", current->pid, current->comm, size, wr_idx, rd_idx, room);
+        UART_DBG_FUNC("--\n");
+        (*written_size) = 0;
+        return -3;
+    }
+    else {
+        /*
+            wr_idx : the position next to write
+            rd_idx : the position next to read
+        */
+        len = min(size, MTKSTP_BUFFER_SIZE - (unsigned int)wr_idx);
+        memcpy(&tx_buf[wr_idx], &data[0], len);
+        memcpy(&tx_buf[0], &data[len], size - len);
+        wr_idx = (wr_idx + size) % MTKSTP_BUFFER_SIZE;
+        UART_DBG_FUNC("r(%d)s(%d)wr_i(%d)rd_i(%d)\n\r", room, size, wr_idx, rd_idx);
+        i++;
+        if (size < 0)
+        {
+            UART_ERR_FUNC("Error(i-%d):[pid(%d)(%s)]len(%d)size(%d)wr_i(%d)rd_i(%d)\n\r", i, current->pid, current->comm, len, size, wr_idx, rd_idx);
+            (*written_size) = 0;
+        }
+        else if (size == 0)
+        {
+            (*written_size) = 0;
+        }
+        else if (size < MAX_PACKET_ALLOWED)
+        {
+            //only size ~(0, 2000) is allowed
+            (*written_size) = stp_uart_tx_wakeup(stp_tty);
+            if(*written_size < 0)
+            {
+                //reset read and write index of tx_buffer, is there any risk?
+                wr_idx = rd_idx = 0;
+                *written_size = 0;
+            }
+        }
+        else
+        {
+            //we filter all packet with size > 2000
+            UART_ERR_FUNC("Warnning(i-%d):[pid(%d)(%s)]len(%d)size(%d)wr_i(%d)rd_i(%d)\n\r", i, current->pid, current->comm, len, size,  wr_idx, rd_idx);
+            (*written_size)= 0;
+        }
+    }
+    #endif
+
+
+    #if 0
+    while((room > 0) && (size > 0))
+    {
+        tx_buf[wr_idx] = data[idx];
+        wr_idx = ((wr_idx + 1) % MTKSTP_BUFFER_SIZE);
+        idx++;
+        room--;
+        size--;
+        (*written_size)++;
+    }
+    #endif
+    //up(&buf_mtx);
+    /*
+        [PatchNeed]
+        spin_lock_irqsave is redundant
+    */
+////    spin_lock_irqsave(&buf_lock, flags);
+
+    /*[PatchNeed]To add a tasklet to shedule Uart Tx*/
+    UART_DBG_FUNC("--\n");
+    return 0;
+}
+
+static int __init mtk_wcn_stp_uart_init(void)
+{
+    static struct tty_ldisc_ops stp_uart_ldisc;
+    int err;
+       int fifo_init_done =0;
+
+    UART_INFO_FUNC("mtk_wcn_stp_uart_init(): MTK STP UART driver\n");
+
+#if  (LDISC_RX == LDISC_RX_TASKLET)
+    err = stp_uart_fifo_init();
+    if (err != 0)
+    {
+        goto init_err;
+    }
+       fifo_init_done = 1;
+    /*init rx tasklet*/
+    tasklet_init(&g_stp_uart_rx_fifo_tasklet, stp_uart_rx_handling, (unsigned long) 0);
+       
+#elif  (LDISC_RX == LDISC_RX_WORK)
+       err = stp_uart_fifo_init();
+       if (err != 0) {
+               UART_ERR_FUNC("stp_uart_fifo_init(WORK) error(%d)\n", err);
+               err = -EFAULT;
+               goto init_err;
+       }
+       fifo_init_done = 1;
+
+       g_stp_uart_rx_work = vmalloc(sizeof(struct work_struct));
+       if (!g_stp_uart_rx_work) {
+               UART_ERR_FUNC("vmalloc work_struct(%d) fail\n", sizeof(struct work_struct));
+               err = -ENOMEM;
+               goto init_err;
+       }
+
+       g_stp_uart_rx_wq = create_singlethread_workqueue("mtk_urxd");
+       if (!g_stp_uart_rx_wq) {
+               UART_ERR_FUNC("create_singlethread_workqueue fail\n");
+               err = -ENOMEM;
+               goto init_err;
+       }
+
+       /* init rx work */
+       INIT_WORK(g_stp_uart_rx_work, stp_uart_rx_worker);
+
+#endif
+
+     /* Register the tty discipline */
+    memset(&stp_uart_ldisc, 0, sizeof (stp_uart_ldisc));
+    stp_uart_ldisc.magic    = TTY_LDISC_MAGIC;
+    stp_uart_ldisc.name     = "n_mtkstp";
+    stp_uart_ldisc.open     = stp_uart_tty_open;
+    stp_uart_ldisc.close    = stp_uart_tty_close;
+    stp_uart_ldisc.read     = stp_uart_tty_read;
+    stp_uart_ldisc.write    = stp_uart_tty_write;
+    stp_uart_ldisc.ioctl    = stp_uart_tty_ioctl;
+    stp_uart_ldisc.poll     = stp_uart_tty_poll;
+    stp_uart_ldisc.receive_buf  = stp_uart_tty_receive;
+    stp_uart_ldisc.write_wakeup = stp_uart_tty_wakeup;
+    stp_uart_ldisc.owner    = THIS_MODULE;
+
+    if ((err = tty_register_ldisc(N_MTKSTP, &stp_uart_ldisc)))
+    {
+        UART_ERR_FUNC("MTK STP line discipline registration failed. (%d)\n", err);
+        goto init_err;
+    }
+
+    /*
+    mtk_wcn_stp_register_if_tx( mtk_wcn_uart_tx);
+    */
+
+    return 0;
+
+init_err:
+       
+#if (LDISC_RX == LDISC_RX_TASKLET)
+               /* nothing */
+               if (fifo_init_done) {
+                       stp_uart_fifo_deinit();
+               }
+#elif (LDISC_RX == LDISC_RX_WORK)
+               if (g_stp_uart_rx_wq) {
+                       destroy_workqueue(g_stp_uart_rx_wq);
+                       g_stp_uart_rx_wq = NULL;
+               }
+               if (g_stp_uart_rx_work) {
+                       vfree(g_stp_uart_rx_work);
+               }
+               if (fifo_init_done) {
+                       stp_uart_fifo_deinit();
+               }
+#endif
+               UART_ERR_FUNC("init fail, return(%d)\n", err);
+       
+               return err;
+
+}
+
+static void __exit mtk_wcn_stp_uart_exit(void)
+{
+    int err;
+
+    mtk_wcn_stp_register_if_tx(STP_UART_IF_TX, NULL);    // unregister if_tx function
+
+    /* Release tty registration of line discipline */
+    if ((err = tty_unregister_ldisc(N_MTKSTP)))
+    {
+        UART_ERR_FUNC("Can't unregister MTK STP line discipline (%d)\n", err);
+    }
+
+#if (LDISC_RX == LDISC_RX_TASKLET)
+    tasklet_kill(&g_stp_uart_rx_fifo_tasklet);
+    stp_uart_fifo_deinit();
+#elif (LDISC_RX == LDISC_RX_WORK)
+       if (g_stp_uart_rx_work) {
+               cancel_work_sync(g_stp_uart_rx_work);
+       }
+       if (g_stp_uart_rx_wq) {
+               destroy_workqueue(g_stp_uart_rx_wq);
+               g_stp_uart_rx_wq = NULL;
+       }
+       if (g_stp_uart_rx_work) {
+               vfree(g_stp_uart_rx_work);
+               g_stp_uart_rx_work = NULL;
+       }
+       stp_uart_fifo_deinit();
+
+#endif
+    return;
+}
+
+module_init(mtk_wcn_stp_uart_init);
+module_exit(mtk_wcn_stp_uart_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("MediaTek Inc WCN_SE_CS3");
+MODULE_DESCRIPTION("STP-HIF UART Interface");
diff --git a/drivers/mtk_wcn_combo/common/linux/wmt_chrdev_wifi.c b/drivers/mtk_wcn_combo/common/linux/wmt_chrdev_wifi.c
new file mode 100755 (executable)
index 0000000..411a2cc
--- /dev/null
@@ -0,0 +1,179 @@
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/sched.h>
+#include <asm/current.h>
+#include <asm/uaccess.h>
+#include <linux/fcntl.h>
+#include <linux/poll.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+#include "wmt_exp.h"
+#include "stp_exp.h"
+
+MODULE_LICENSE("Dual BSD/GPL");
+
+#define WIFI_DRIVER_NAME "mtk_wmt_WIFI_chrdev"
+#if WMT_PLAT_APEX
+#define WIFI_DEV_MAJOR 194 // never used number
+#else
+#define WIFI_DEV_MAJOR 153 // never used number
+#endif
+
+#define PFX                         "[MTK-WIFI] "
+#define WIFI_LOG_DBG                  3
+#define WIFI_LOG_INFO                 2
+#define WIFI_LOG_WARN                 1
+#define WIFI_LOG_ERR                  0
+
+
+unsigned int gDbgLevel = WIFI_LOG_INFO;
+
+#define WIFI_DBG_FUNC(fmt, arg...)    if(gDbgLevel >= WIFI_LOG_DBG){ printk(PFX "%s: "  fmt, __FUNCTION__ ,##arg);}
+#define WIFI_INFO_FUNC(fmt, arg...)   if(gDbgLevel >= WIFI_LOG_INFO){ printk(PFX "%s: "  fmt, __FUNCTION__ ,##arg);}
+#define WIFI_WARN_FUNC(fmt, arg...)   if(gDbgLevel >= WIFI_LOG_WARN){ printk(PFX "%s: "  fmt, __FUNCTION__ ,##arg);}
+#define WIFI_ERR_FUNC(fmt, arg...)    if(gDbgLevel >= WIFI_LOG_ERR){ printk(PFX "%s: "   fmt, __FUNCTION__ ,##arg);}
+#define WIFI_TRC_FUNC(f)              if(gDbgLevel >= WIFI_LOG_DBG){printk(PFX "<%s> <%d>\n", __FUNCTION__, __LINE__);}
+
+#define VERSION "1.0"
+
+static int WIFI_devs = 1;        /* device count */
+static int WIFI_major = WIFI_DEV_MAJOR;       /* dynamic allocation */
+module_param(WIFI_major, uint, 0);
+static struct cdev WIFI_cdev;
+volatile int retflag = 0;
+static struct semaphore wr_mtx;
+
+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)
+{
+    int retval = -EIO;
+    char local[4] = {0};
+    static int opened = 0;
+
+    down(&wr_mtx);
+
+    if (count > 0) {
+
+        if (0 == copy_from_user(local, buf, (count > 4) ? 4 : count)) {
+            WIFI_INFO_FUNC("WIFI_write %c\n", local[0]);
+            if (local[0] == '0' && opened == 1) {
+                //TODO
+                //Configure the EINT pin to GPIO mode.
+
+                if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_off(WMTDRV_TYPE_WIFI)) {
+                    WIFI_INFO_FUNC("WMT turn off WIFI fail!\n");
+                }
+                else {
+                    WIFI_INFO_FUNC("WMT turn off WIFI OK!\n");
+                    opened = 0;
+                    retval = count;
+                }
+            }
+            else if (local[0] == '1') {
+                //TODO
+                //Disable EINT(external interrupt), and set the GPIO to EINT mode.
+
+                if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_WIFI)) {
+                    WIFI_WARN_FUNC("WMT turn on WIFI fail!\n");
+                }
+                else {
+                    opened = 1;
+                    retval = count;
+                    WIFI_INFO_FUNC("WMT turn on WIFI success!\n");
+                }
+            }
+
+        }
+    }
+
+    up(&wr_mtx);
+    return (retval);
+}
+
+
+struct file_operations WIFI_fops = {
+    .open = WIFI_open,
+    .release = WIFI_close,
+    .write = WIFI_write,
+};
+
+static int WIFI_init(void)
+{
+    dev_t dev = MKDEV(WIFI_major, 0);
+    int alloc_ret = 0;
+    int cdev_err = 0;
+
+    /*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;
+    }
+
+    sema_init(&wr_mtx, 1);
+
+    WIFI_INFO_FUNC("%s driver(major %d) installed.\n", WIFI_DRIVER_NAME, WIFI_major);
+    retflag = 0;
+
+    return 0;
+
+error:
+    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;
+
+    cdev_del(&WIFI_cdev);
+    unregister_chrdev_region(dev, WIFI_devs);
+
+    WIFI_INFO_FUNC("%s driver removed.\n", WIFI_DRIVER_NAME);
+}
+
+module_init(WIFI_init);
+module_exit(WIFI_exit);
+
diff --git a/drivers/mtk_wcn_combo/common/linux/wmt_dev.c b/drivers/mtk_wcn_combo/common/linux/wmt_dev.c
new file mode 100755 (executable)
index 0000000..27f792d
--- /dev/null
@@ -0,0 +1,1208 @@
+/*! \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
+********************************************************************************
+*/
+
+
+
+/*******************************************************************************
+*                    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 "wmt_tm.h"
+#include "psm_core.h"
+#include "stp_core.h"
+#include "stp_exp.h"
+#include "hif_sdio.h"
+#include "wmt_dbg.h"
+
+
+#define MTK_WMT_VERSION  "Combo WMT Driver - v1.0"
+#define MTK_WMT_DATE     "2011/10/04"
+#define MTK_COMBO_DRIVER_VERSION "APEX.WCN.MT6620.JB2.MP.V1.0"
+#define WMT_DEV_MAJOR 190 // never used number
+#define WMT_DEV_NUM 1
+
+
+
+#define WMT_DRIVER_NAME "mtk_stp_wmt"
+
+
+P_OSAL_EVENT gpRxEvent = NULL;
+
+UINT32 u4RxFlag = 0x0;
+static atomic_t gRxCount = ATOMIC_INIT(0);
+
+/* Linux UCHAR device */
+static int gWmtMajor = WMT_DEV_MAJOR;
+static struct cdev gWmtCdev;
+static atomic_t gWmtRefCnt = ATOMIC_INIT(0);
+/* WMT driver information */
+static UINT8 gLpbkBuf[WMT_LPBK_BUF_LEN] = {0}; //modify for support 1024 loopback
+static UINT32 gLpbkBufLog; // George LPBK debug
+
+P_WMT_PATCH_INFO pPatchInfo = NULL;
+UINT32 pAtchNum = 0;
+
+
+/*******************************************************************************
+*                          F U N C T I O N S
+********************************************************************************
+*/
+
+VOID wmt_dev_rx_event_cb (VOID)
+{
+    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 (
+    UCHAR *pName,
+    const u8 **ppBufPtr,
+    INT32 offset,
+    INT32 padSzBuf
+    )
+{
+    INT32 iRet = -1;
+    struct file *fd;
+    //ssize_t iRet;
+    INT32 file_len;
+    INT32 read_len;
+    void *pBuf;
+
+    //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 (!fd || IS_ERR(fd) || !fd->f_op || !fd->f_op->read) {
+        WMT_ERR_FUNC("failed to open or read!(0x%p, %d, %d)\n", fd, cred->fsuid, cred->fsgid);
+        return -1;
+    }
+
+    file_len = fd->f_path.dentry->d_inode->i_size;
+    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;
+            }
+        }
+
+        read_len = fd->f_op->read(fd, pBuf + padSzBuf, file_len, &fd->f_pos);
+        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 (
+    UCHAR *pPatchName,
+    osal_firmware **ppPatch,
+    INT32 padSzBuf
+    )
+{
+    INT32 iRet = -1;
+    osal_firmware *pfw;
+    uid_t orig_uid;
+    gid_t orig_gid;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29))
+    //struct cred *cred = get_task_cred(current);
+    struct cred *cred = (struct cred *)get_current_cred();
+#endif
+
+    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;
+    }
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29))
+    orig_uid = cred->fsuid;
+    orig_gid = cred->fsgid;
+    cred->fsuid = cred->fsgid = 0;
+#else
+    orig_uid = current->fsuid;
+    orig_gid = current->fsgid;
+    current->fsuid = current->fsgid = 0;
+#endif
+
+    set_fs(get_ds());
+
+    /* load patch file from fs */
+    iRet = wmt_dev_read_file(pPatchName, &pfw->data, 0, padSzBuf);
+    set_fs(orig_fs);
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29))
+    cred->fsuid = orig_uid;
+    cred->fsgid = orig_gid;
+#else
+    current->fsuid = orig_uid;
+    current->fsgid = orig_gid;
+#endif
+
+    if (iRet > 0) {
+        pfw->size = iRet;
+        *ppPatch = pfw;
+        WMT_DBG_FUNC("load (%s) to addr(0x%p) success\n", pPatchName, pfw->data);
+        return 0;
+    }
+    else {
+        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)
+{
+       if (pPatchInfo) {
+               kfree(pPatchInfo);
+               pPatchInfo = NULL;
+       }
+}
+
+
+MTK_WCN_BOOL wmt_dev_is_file_exist(UCHAR *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;
+
+}
+
+#if  defined(CONFIG_THERMAL) &&  defined(CONFIG_THERMAL_OPEN)
+static unsigned long count_last_access_sdio = 0;    
+static unsigned long count_last_access_uart = 0;
+static unsigned long jiffies_last_poll = 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;
+}
+
+extern INT32 wmt_dev_tra_uart_update(void)
+{          
+    count_last_access_uart += 1;  
+    //WMT_INFO_FUNC("jiffies_last_access_uart: jiffies = %ul\n", jiffies);
+
+    return 0;
+}
+
+static UINT32 wmt_dev_tra_sdio_poll(void)
+{    
+    #define TIME_THRESHOLD_TO_TEMP_QUERY 3000 
+    #define COUNT_THRESHOLD_TO_TEMP_QUERY 200
+
+    unsigned long sdio_during_count = 0;
+    unsigned long poll_during_time = 0;
+
+    if(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;
+    } 
+      
+    sdio_during_count = count_last_access_sdio;
+
+    if(sdio_during_count < COUNT_THRESHOLD_TO_TEMP_QUERY)
+    {
+        WMT_DBG_FUNC("**sdio_during_count = %lu < %lu, not to query\n", 
+            sdio_during_count, COUNT_THRESHOLD_TO_TEMP_QUERY);
+        return -1;
+    }
+
+    count_last_access_sdio = 0;
+    jiffies_last_poll = jiffies;
+
+    WMT_INFO_FUNC("**poll_during_time = %lu > %lu, sdio_during_count = %lu > %lu, query\n", 
+            jiffies_to_msecs(poll_during_time), TIME_THRESHOLD_TO_TEMP_QUERY,
+            jiffies_to_msecs(sdio_during_count) , COUNT_THRESHOLD_TO_TEMP_QUERY);
+
+    return 0;
+}
+
+#if 0
+static UINT32 wmt_dev_tra_uart_poll(void)
+{   
+    //we not support the uart case.
+    return -1;
+}
+#endif
+
+static INT32 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 = 0;
+    static struct timeval query_time, now_time;
+
+    INT8  query_cond = 0;
+    INT32 current_temp = 0;
+    INT32 index = 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_INFO_FUNC("high temperature (current temp = %d), we must keep querying temp temperature..\n", temp_table[index]);
+       }            
+    }
+
+    do_gettimeofday(&now_time);
+#if 1
+    // Query condition 2:
+    // Moniter the hif_sdio activity to decide if we have the need to query temperature.
+    if(!query_cond)
+    {
+        if( wmt_dev_tra_sdio_poll()==0)
+        {
+            query_cond = 1;
+            WMT_INFO_FUNC("sdio traffic , we must query temperature..\n");
+        }
+        else
+        {
+            WMT_DBG_FUNC("sdio 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)
+    {
+        if( (now_time.tv_sec < query_time.tv_sec) || //time overflow, we refresh temp table again for simplicity!
+            ((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);
+        wmt_lib_notify_stp_sleep();
+        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 current_temp;
+}
+
+static INT32 wmt_dev_tm_temp_set(int temp)
+{
+   
+    //TODO: now we no export the APIs to external modules
+    //This will affect the performance, so we disable the function temporarily.
+    
+    return 0;
+}
+
+static INT32 wmt_dev_tm_setup(void)
+{
+    static struct wmt_thermal_ctrl_ops thermal_ops;
+    struct wmt_thermal_ctrl_ops *p_thermal_ops = &thermal_ops;
+    
+    p_thermal_ops->query_temp = wmt_dev_tm_temp_query;
+    p_thermal_ops->set_temp = wmt_dev_tm_temp_set;
+
+    wmt_tm_init(p_thermal_ops);
+    wmt_tm_init_rt();
+
+    return 0;
+}
+#else
+//STP-UART will access the symbol, so we keep symbol exist even when CONFIG_THERMAL is not support
+extern INT32 wmt_dev_tra_uart_update(void)
+{          
+    return 0;
+}
+#endif
+
+
+
+ssize_t
+WMT_write (
+    struct file *filp,
+    const char __user *buf,
+    size_t count,
+    loff_t *f_pos
+    )
+{
+    INT32 iRet = 0;
+    UCHAR 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;
+    PUCHAR 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
+    )
+{
+#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)
+
+
+
+    INT32 iRet = 0;
+    UCHAR pBuffer[NAME_MAX + 1];
+    WMT_DBG_FUNC("cmd (%u), arg (0x%lx)\n", cmd, arg);
+    switch(cmd) {
+    case WMT_IOCTL_SET_PATCH_NAME: /* patch location */
+        {
+            
+            if (copy_from_user(pBuffer, (void *)arg, NAME_MAX)) {
+                iRet = -EFAULT;
+                break;
+            }
+            pBuffer[NAME_MAX] = '\0';
+            wmt_lib_set_patch_name(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] = (UINT32)&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\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("OPID(%d) type(%d) buf tail(0x%08x) fail\n",
+                pOp->op.opId,
+                    pOp->op.au4OpData[0],
+                    gLpbkBufLog);
+                iRet = -1;
+                break;
+            }
+            else {
+                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(ULONG) + sizeof(UCHAR[2048]), gLpbkBuf, iRet)) {
+                    iRet = -EFAULT;
+                    break;
+                }
+            }
+        }while(0);
+
+        break;
+#if 0
+        case 9:
+        {
+            #define LOG_BUF_SZ 300
+            UCHAR buf[LOG_BUF_SZ];
+            INT32 len = 0;
+            INT32 remaining = 0;
+
+            remaining = mtk_wcn_stp_btm_get_dmp(buf, &len);
+
+            if(remaining == 0){
+                WMT_DBG_FUNC("waiting dmp \n");
+                wait_event_interruptible(dmp_wq, dmp_flag != 0);
+                dmp_flag = 0;
+                remaining = mtk_wcn_stp_btm_get_dmp(buf, &len);
+
+                //WMT_INFO_FUNC("len = %d ###%s#\n", len, buf);
+            } else {
+                WMT_LOUD_FUNC("no waiting dmp \n");
+            }
+
+            if(unlikely((len+sizeof(INT32)) >= LOG_BUF_SZ)){
+                WMT_ERR_FUNC("len is larger buffer\n");
+                iRet = -EFAULT;
+                goto fail_exit;
+            }
+
+            buf[sizeof(INT32)+len]='\0';
+
+            if (copy_to_user((void *)arg, (UCHAR *)&len, sizeof(INT32))){
+                iRet = -EFAULT;
+                goto fail_exit;
+            }
+
+            if (copy_to_user((void *)arg + sizeof(INT32), buf, len)){
+                iRet = -EFAULT;
+                goto fail_exit;
+            }
+        }
+        break;
+
+        case 10:
+        {
+            WMT_INFO_FUNC("Enable combo trace32 dump\n");
+            wmt_cdev_t32dmp_enable();
+            WMT_INFO_FUNC("Enable STP debugging mode\n");
+            mtk_wcn_stp_dbg_enable();
+        }
+        break;
+
+        case 11:
+        {
+            WMT_INFO_FUNC("Disable combo trace32 dump\n");
+            wmt_cdev_t32dmp_disable();
+            WMT_INFO_FUNC("Disable STP debugging mode\n");
+            mtk_wcn_stp_dbg_disable();
+        }
+        break;
+#endif
+        
+        case 10:
+        {
+                       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);
+        }
+            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_INFO_FUNC(" get patch num from launcher = %d\n",pAtchNum);
+                       wmt_lib_set_patch_num(pAtchNum);
+                       pPatchInfo = kzalloc(sizeof(WMT_PATCH_INFO)*pAtchNum,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 = 0;
+                       
+                       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("current download seq no is %d,patch name is %s,addres info is 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_PORT_NAME: {
+            CHAR cUartName[NAME_MAX + 1];
+            if (copy_from_user(cUartName, (void *)arg, NAME_MAX)) {
+                iRet = -EFAULT;
+                break;
+            }
+            cUartName[NAME_MAX] = '\0';
+            wmt_lib_set_uart_name(cUartName);
+        }
+        break;
+               
+               case WMT_IOCTL_WMT_CFG_NAME:
+               {
+                       CHAR cWmtCfgName[NAME_MAX + 1];
+            if (copy_from_user(cWmtCfgName, (void *)arg, NAME_MAX)) {
+                iRet = -EFAULT;
+                break;
+            }
+            cWmtCfgName[NAME_MAX] = '\0';
+                       wmt_conf_set_cfg_file(cWmtCfgName);
+               }
+               break;
+               case WMT_IOCTL_WMT_QUERY_CHIPID:
+               {
+                       iRet = mtk_wcn_hif_sdio_query_chipid(1);
+               }
+               break;
+               case WMT_IOCTL_WMT_TELL_CHIPID:
+               {
+                       iRet = mtk_wcn_hif_sdio_tell_chipid(arg);
+                       if (0x6628 == arg)
+                       {
+                           wmt_lib_merge_if_flag_ctrl(1);
+                       }
+                       else
+                       {
+                           wmt_lib_merge_if_flag_ctrl(0);
+                       }
+               }
+               break;
+               case WMT_IOCTL_WMT_COREDUMP_CTRL:
+               {
+                   if (0 == arg)
+                   {
+                       mtk_wcn_stp_coredump_flag_ctrl(0);
+                   }
+                       else
+                       {
+                           mtk_wcn_stp_coredump_flag_ctrl(1);
+                       }
+               }
+               break;
+    default:
+        iRet = -EINVAL;
+        WMT_WARN_FUNC("unknown cmd (%d)\n", cmd);
+        break;
+    }
+
+
+    return iRet;
+}
+
+static int WMT_open(struct inode *inode, struct file *file)
+{
+    WMT_INFO_FUNC("major %d minor %d (pid %d)\n",
+        imajor(inode),
+        iminor(inode),
+        current->pid
+        );
+
+    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;
+}
+
+ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
+ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
+long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
+
+struct file_operations gWmtFops = {
+    .open = WMT_open,
+    .release = WMT_close,
+    .read = WMT_read,
+    .write = WMT_write,
+//    .ioctl = WMT_ioctl,
+    .unlocked_ioctl = WMT_unlocked_ioctl,
+    .poll = WMT_poll,
+};
+
+
+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);
+    WMT_INFO_FUNC("COMBO Driver Version= %s\n" , MTK_COMBO_DRIVER_VERSION);
+    /* Prepare a UCHAR device */
+    /*static allocate chrdev*/
+
+    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 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  defined(CONFIG_THERMAL) &&  defined(CONFIG_THERMAL_OPEN)
+    WMT_INFO_FUNC("wmt_dev_tm_setup\n");
+    wmt_dev_tm_setup();
+    mtk_wcn_hif_sdio_update_cb_reg(wmt_dev_tra_sdio_update);
+#endif
+
+    WMT_INFO_FUNC("success \n");
+    return 0;
+
+error:
+    wmt_lib_deinit();
+#if CFG_WMT_DBG_SUPPORT    
+    wmt_dev_dbg_remove();
+#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);
+
+#if  defined(CONFIG_THERMAL) &&  defined(CONFIG_THERMAL_OPEN)
+               wmt_tm_deinit_rt();
+               wmt_tm_deinit();
+#endif
+
+    wmt_lib_deinit();
+    
+#if CFG_WMT_DBG_SUPPORT
+    wmt_dev_dbg_remove();
+#endif
+    cdev_del(&gWmtCdev);
+    unregister_chrdev_region(dev, WMT_DEV_NUM);
+    gWmtMajor = -1;
+#ifdef MTK_WMT_WAKELOCK_SUPPORT
+    WMT_WARN_FUNC("destroy func_on_off_wake_lock\n");
+    wake_lock_destroy(&func_on_off_wake_lock);
+#endif
+
+    stp_drv_exit();
+
+    WMT_INFO_FUNC("done\n");
+}
+
+module_init(WMT_init);
+module_exit(WMT_exit);
+//MODULE_LICENSE("Proprietary");
+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/mtk_wcn_combo/common/linux/wmt_tm.c b/drivers/mtk_wcn_combo/common/linux/wmt_tm.c
new file mode 100755 (executable)
index 0000000..5a6b71d
--- /dev/null
@@ -0,0 +1,1402 @@
+#if WMT_PLAT_ALPS
+
+#include <linux/thermal.h>
+#include <linux/xlog.h>
+#include <linux/proc_fs.h>
+#include <asm/uaccess.h>
+#include "wmt_tm.h"
+#include <mach/mtk_thermal_monitor.h>
+
+#include <linux/timer.h>
+#include <linux/pid.h>
+/* For using net dev + */
+#include <linux/netdevice.h>
+/* For using net dev - */
+
+#if  defined(CONFIG_THERMAL) &&  defined(CONFIG_THERMAL_OPEN)
+
+static int wmt_tm_debug_log = 0;
+#define wmt_tm_dprintk(fmt, args...)   \
+do {                                    \
+    if (wmt_tm_debug_log) {                \
+        xlog_printk(ANDROID_LOG_DEBUG, "Power/WMT_Thermal", fmt, ##args); \
+    }                                   \
+} while(0)
+
+#define wmt_tm_printk(fmt, args...)   \
+do {                                    \
+    xlog_printk(ANDROID_LOG_DEBUG, "Power/WMT_Thermal", fmt, ##args); \
+} while(0)
+
+#define wmt_tm_info(fmt, args...)   \
+do {                                    \
+    xlog_printk(ANDROID_LOG_INFO, "Power/WMT_Thermal", fmt, ##args); \
+} while(0)
+
+struct linux_thermal_ctrl_if {
+    int kernel_mode;
+    int interval;
+    struct thermal_zone_device *thz_dev;
+    struct thermal_cooling_device *cl_dev;
+    struct thermal_cooling_device *cl_pa1_dev;
+    struct thermal_cooling_device *cl_pa2_dev;
+    struct thermal_cooling_device *cl_pa3_dev;
+};
+
+struct wmt_thermal_ctrl_if {
+    struct wmt_thermal_ctrl_ops ops;
+};
+
+typedef struct wmt_tm {
+   struct linux_thermal_ctrl_if linux_if;
+   struct wmt_thermal_ctrl_if   wmt_if;
+}wmt_tm_t;
+
+struct wmt_stats {
+   unsigned long pre_time;
+   unsigned long pre_tx_bytes;
+};
+
+static struct timer_list wmt_stats_timer;
+static struct wmt_stats wmt_stats_info;
+static unsigned long pre_time;
+static unsigned long tx_throughput;
+
+/*New Wifi throttling Algo+*/
+//over_up_time * polling interval > up_duration --> throttling
+static unsigned int over_up_time = 0; //polling time
+static unsigned int up_duration = 30; //sec
+static unsigned int up_denominator = 2;
+static unsigned int up_numerator = 1;
+
+//below_low_time * polling interval > low_duration --> throttling
+static unsigned int below_low_time = 0; //polling time
+static unsigned int low_duration = 10; //sec
+static unsigned int low_denominator = 2;
+static unsigned int low_numerator = 3;
+
+static unsigned int low_rst_time = 0;
+static unsigned int low_rst_max = 3;
+/*New Wifi throttling Algo-*/
+
+#define MAX_LEN        256
+#define COOLER_THRO_NUM 3
+#define COOLER_NUM 10
+#define ONE_MBITS_PER_SEC 1000
+
+static unsigned int tm_pid = 0;
+static unsigned int tm_input_pid = 0;
+static unsigned int tm_wfd_stat = 0;
+static struct task_struct g_task;
+static struct task_struct *pg_task = &g_task;
+
+/* +Cooler info+ */
+static int g_num_trip = COOLER_THRO_NUM + 1;
+static char g_bind0[20]="mtktswmt-pa1";
+static char g_bind1[20]="mtktswmt-pa2";
+static char g_bind2[20]="mtktswmt-pa3";
+static char g_bind3[20]="mtktswmt-sysrst";
+static char g_bind4[20]={0};
+static char g_bind5[20]={0};
+static char g_bind6[20]={0};
+static char g_bind7[20]={0};
+static char g_bind8[20]={0};
+static char g_bind9[20]={0};
+
+
+static unsigned int cl_dev_state =0;
+static unsigned int cl_pa1_dev_state =0;
+static unsigned int cl_pa2_dev_state =0;
+/*static unsigned int cl_pa3_dev_state =0;*/
+static unsigned int g_trip_temp[COOLER_NUM] = {85000,85000,85000,85000,0,0,0,0,0,0};
+/*static int g_thro[COOLER_THRO_NUM] = {10 * ONE_MBITS_PER_SEC, 5 * ONE_MBITS_PER_SEC, 1 * ONE_MBITS_PER_SEC};*/
+static int g_thermal_trip[COOLER_NUM] = {0,0,0,0,0,0,0,0,0,0};
+/* -Cooler info- */
+
+wmt_tm_t g_wmt_tm;
+wmt_tm_t *pg_wmt_tm = &g_wmt_tm;
+
+static int wmt_thz_bind(struct thermal_zone_device *,
+                    struct thermal_cooling_device *);
+static int wmt_thz_unbind(struct thermal_zone_device *,
+                    struct thermal_cooling_device *);
+static int wmt_thz_get_temp(struct thermal_zone_device *,
+             unsigned long *);
+static int wmt_thz_get_mode(struct thermal_zone_device *,
+                        enum thermal_device_mode *);
+static int wmt_thz_set_mode(struct thermal_zone_device *,
+                    enum thermal_device_mode);
+static int wmt_thz_get_trip_type(struct thermal_zone_device *, int,
+                    enum thermal_trip_type *);
+static int wmt_thz_get_trip_temp(struct thermal_zone_device *, int,
+                        unsigned long *);
+static int wmt_thz_get_crit_temp(struct thermal_zone_device *,
+             unsigned long *);
+static int wmt_cl_get_max_state(struct thermal_cooling_device *,
+             unsigned long *);
+static int wmt_cl_get_cur_state(struct thermal_cooling_device *,
+             unsigned long *);
+static int wmt_cl_set_cur_state(struct thermal_cooling_device *,
+             unsigned long);
+
+static int wmt_cl_pa1_get_max_state(struct thermal_cooling_device *,
+             unsigned long *);
+static int wmt_cl_pa1_get_cur_state(struct thermal_cooling_device *,
+             unsigned long *);
+static int wmt_cl_pa1_set_cur_state(struct thermal_cooling_device *,
+             unsigned long);
+
+static int wmt_cl_pa2_get_max_state(struct thermal_cooling_device *,
+             unsigned long *);
+static int wmt_cl_pa2_get_cur_state(struct thermal_cooling_device *,
+             unsigned long *);
+static int wmt_cl_pa2_set_cur_state(struct thermal_cooling_device *,
+             unsigned long);
+
+#ifdef NEVER
+static int wmt_cl_pa3_get_max_state(struct thermal_cooling_device *,
+             unsigned long *);
+static int wmt_cl_pa3_get_cur_state(struct thermal_cooling_device *,
+             unsigned long *);
+static int wmt_cl_pa3_set_cur_state(struct thermal_cooling_device *,
+             unsigned long);
+#endif /* NEVER */
+
+static struct thermal_zone_device_ops wmt_thz_dev_ops = {
+       .bind = wmt_thz_bind,
+       .unbind = wmt_thz_unbind,
+       .get_temp = wmt_thz_get_temp,
+       .get_mode = wmt_thz_get_mode,
+       .set_mode = wmt_thz_set_mode,
+       .get_trip_type = wmt_thz_get_trip_type,
+       .get_trip_temp = wmt_thz_get_trip_temp,
+       .get_crit_temp = wmt_thz_get_crit_temp,
+};
+
+static struct thermal_cooling_device_ops mtktspa_cooling_sysrst_ops = {
+       .get_max_state = wmt_cl_get_max_state,
+       .get_cur_state = wmt_cl_get_cur_state,
+       .set_cur_state = wmt_cl_set_cur_state,
+};
+
+static struct thermal_cooling_device_ops mtktspa_cooling_pa1_ops = {
+       .get_max_state = wmt_cl_pa1_get_max_state,
+       .get_cur_state = wmt_cl_pa1_get_cur_state,
+       .set_cur_state = wmt_cl_pa1_set_cur_state,
+};
+
+static struct thermal_cooling_device_ops mtktspa_cooling_pa2_ops = {
+       .get_max_state = wmt_cl_pa2_get_max_state,
+       .get_cur_state = wmt_cl_pa2_get_cur_state,
+       .set_cur_state = wmt_cl_pa2_set_cur_state,
+};
+
+#ifdef NEVER
+static struct thermal_cooling_device_ops mtktspa_cooling_pa3_ops = {
+       .get_max_state = wmt_cl_pa3_get_max_state,
+       .get_cur_state = wmt_cl_pa3_get_cur_state,
+       .set_cur_state = wmt_cl_pa3_set_cur_state,
+};
+#endif /* NEVER */
+
+static unsigned long get_tx_bytes(void)
+{
+       struct net_device *dev;
+       struct net *net;
+       unsigned long tx_bytes = 0;
+
+       read_lock(&dev_base_lock);
+       for_each_net(net) {
+               for_each_netdev(net, dev) {
+                       if(!strncmp(dev->name, "wlan", 4) || !strncmp(dev->name, "ap", 2) || !strncmp(dev->name, "p2p", 3)) {
+                               struct rtnl_link_stats64 temp;
+                               const struct rtnl_link_stats64 *stats = dev_get_stats(dev, &temp);
+                               tx_bytes = tx_bytes + stats->tx_bytes;
+                       }
+               }
+       }
+       read_unlock(&dev_base_lock);
+       return tx_bytes;
+}
+
+static int wmt_cal_stats(unsigned long data)
+{
+       struct wmt_stats *stats_info = (struct wmt_stats*) data;
+       struct timeval cur_time;
+
+       wmt_tm_dprintk("[%s] pre_time=%lu, pre_data=%lu\n", __func__, pre_time, stats_info->pre_tx_bytes);
+
+       do_gettimeofday(&cur_time);
+
+       if (pre_time != 0 && cur_time.tv_sec > pre_time) {
+               unsigned long tx_bytes = get_tx_bytes();
+               if (tx_bytes > stats_info->pre_tx_bytes) {
+
+                       tx_throughput = ((tx_bytes - stats_info->pre_tx_bytes) / (cur_time.tv_sec - pre_time)) >> 7;
+
+                       wmt_tm_dprintk("[%s] cur_time=%lu, cur_data=%lu, tx_throughput=%luKb/s\n", __func__, cur_time.tv_sec, tx_bytes, tx_throughput );
+
+                       stats_info->pre_tx_bytes = tx_bytes;
+               } else if (tx_bytes < stats_info->pre_tx_bytes) {
+                       /* Overflow */
+                       tx_throughput = ((0xffffffff - stats_info->pre_tx_bytes + tx_bytes) / (cur_time.tv_sec - pre_time)) >> 7;;
+                       stats_info->pre_tx_bytes = tx_bytes;
+                       wmt_tm_dprintk("[%s] cur_tx(%lu) < pre_tx\n", __func__, tx_bytes);
+               } else {
+                       /* No traffic */
+                       tx_throughput = 0;
+                       wmt_tm_dprintk("[%s] cur_tx(%lu) = pre_tx\n", __func__, tx_bytes);
+               }
+       } else {
+               /* Overflow possible ??*/
+               tx_throughput = 0;
+               wmt_tm_printk("[%s] cur_time(%lu) < pre_time\n", __func__, cur_time.tv_sec);
+       }
+
+       pre_time = cur_time.tv_sec;
+       wmt_tm_dprintk("[%s] pre_time=%lu, tv_sec=%lu\n",__func__, pre_time, cur_time.tv_sec);
+
+       wmt_stats_timer.expires = jiffies + 1 * HZ;
+       add_timer(&wmt_stats_timer);
+       return 0;
+}
+
+static int wmt_thz_bind(struct thermal_zone_device *thz_dev,
+                    struct thermal_cooling_device *cool_dev)
+{
+    struct linux_thermal_ctrl_if *p_linux_if = 0;
+    int    table_val = 0;
+
+    wmt_tm_dprintk("[%s]\n", __func__);
+
+    if (pg_wmt_tm) {
+       p_linux_if = &pg_wmt_tm->linux_if;
+    } else {
+       return -EINVAL;
+    }
+    #ifdef NEVER
+    /* cooling devices */
+    if (cool_dev != p_linux_if->cl_dev)
+    {
+        return 0;
+    }
+    #endif
+
+    if(!strcmp(cool_dev->type, g_bind0)) {
+        table_val = 0;
+        wmt_tm_printk("[%s] %s\n", __func__, cool_dev->type);
+    } else if(!strcmp(cool_dev->type, g_bind1)) {
+        table_val = 1;
+        wmt_tm_printk("[%s] %s\n", __func__, cool_dev->type);
+    } else if(!strcmp(cool_dev->type, g_bind2)) {
+        table_val = 2;
+        wmt_tm_printk("[%s]] %s\n", __func__, cool_dev->type);
+    } else if(!strcmp(cool_dev->type, g_bind3)) {
+        table_val = 3;
+        wmt_tm_printk("[%s]] %s\n", __func__, cool_dev->type);
+    } else
+        return 0;
+
+    if (mtk_thermal_zone_bind_cooling_device(thz_dev, table_val, cool_dev)) {
+        wmt_tm_info("[%s] binding fail\n", __func__);
+        return -EINVAL;
+    } else {
+        wmt_tm_printk("[%s]] binding OK\n", __func__);
+    }
+
+    return 0;
+
+}
+static int wmt_thz_unbind(struct thermal_zone_device *thz_dev,
+                    struct thermal_cooling_device *cool_dev)
+{
+    struct linux_thermal_ctrl_if *p_linux_if = 0;
+    int    table_val = 0;
+
+    wmt_tm_dprintk("[wmt_thz_unbind] \n");
+
+    if (pg_wmt_tm) {
+       p_linux_if = &pg_wmt_tm->linux_if;
+    } else {
+       return -EINVAL;
+    }
+#if 0
+    /* cooling devices */
+    if (cool_dev == p_linux_if->cl_dev)
+    {
+        table_val= 0;
+    }
+    else
+    {
+        wmt_tm_dprintk("[wmt_thz_unbind] unbind device fail..!\n");
+        return -EINVAL;
+    }
+#endif
+
+    if(!strcmp(cool_dev->type, g_bind0)) {
+        table_val = 0;
+        wmt_tm_printk("[wmt_thz_unbind] %s\n", cool_dev->type);
+    } else if(!strcmp(cool_dev->type, g_bind1)) {
+        table_val = 1;
+        wmt_tm_printk("[wmt_thz_unbind] %s\n", cool_dev->type);
+    } else if(!strcmp(cool_dev->type, g_bind2)) {
+        table_val = 2;
+        wmt_tm_printk("[wmt_thz_unbind] %s\n", cool_dev->type);
+    } else if(!strcmp(cool_dev->type, g_bind3)) {
+        table_val = 3;
+        wmt_tm_printk("[wmt_thz_unbind] %s\n", cool_dev->type);
+    } else
+        return 0;
+
+    if (thermal_zone_unbind_cooling_device(thz_dev, table_val, cool_dev)) {
+           wmt_tm_info("[wmt_thz_unbind] error unbinding cooling dev\n");
+               return -EINVAL;
+       } else {
+           wmt_tm_printk("[wmt_thz_unbind] unbinding OK\n");
+    }
+
+       return 0;
+}
+
+static int wmt_thz_get_temp(struct thermal_zone_device *thz_dev,
+             unsigned long *pv)
+{
+    struct wmt_thermal_ctrl_ops *p_des;
+    int temp = 0;
+
+    *pv = 0;
+    if(pg_wmt_tm) {
+        p_des = &pg_wmt_tm->wmt_if.ops;
+        temp = p_des->query_temp();
+
+        //temp = ((temp & 0x80) == 0x0)?temp:(-1)*temp ;
+         temp = ((temp & 0x80) == 0x0)?temp:(-1)*(temp & 0x7f);
+        *pv =  temp*1000;
+
+        wmt_tm_dprintk("[wmt_thz_get_temp] temp = %d\n", temp);
+
+        if(temp > 100 || temp < 5)
+            wmt_tm_info("[wmt_thz_get_temp] temp = %d\n", temp);
+    }
+
+    return 0;
+}
+
+static int wmt_thz_get_mode(struct thermal_zone_device *thz_dev,
+                        enum thermal_device_mode *mode)
+{
+    struct linux_thermal_ctrl_if *p_linux_if = 0;
+//    int    kernel_mode = 0;
+
+    wmt_tm_dprintk("[%s]\n", __func__);
+
+    if (pg_wmt_tm) {
+       p_linux_if = &pg_wmt_tm->linux_if;
+    } else {
+       wmt_tm_dprintk("[%s] fail! \n", __func__);
+       return -EINVAL;
+    }
+
+    wmt_tm_dprintk("[%s] %d\n", __func__, p_linux_if->kernel_mode);
+
+    *mode = (p_linux_if->kernel_mode) ? THERMAL_DEVICE_ENABLED
+                            : THERMAL_DEVICE_DISABLED;
+
+       return 0;
+}
+
+static int wmt_thz_set_mode(struct thermal_zone_device *thz_dev,
+                    enum thermal_device_mode mode)
+{
+    struct linux_thermal_ctrl_if *p_linux_if = 0;
+
+    wmt_tm_dprintk("[%s]\n", __func__);
+
+
+    if(pg_wmt_tm) {
+       p_linux_if = &pg_wmt_tm->linux_if;
+    } else {
+       wmt_tm_dprintk("[%s] fail! \n", __func__);
+       return -EINVAL;
+    }
+
+    wmt_tm_dprintk("[%s] %d\n", __func__, mode);
+
+    p_linux_if->kernel_mode = mode;
+
+       return 0;
+
+}
+
+static int wmt_thz_get_trip_type(struct thermal_zone_device *thz_dev, int trip,
+                    enum thermal_trip_type *type)
+{
+    wmt_tm_dprintk("[mtktspa_get_trip_type] %d\n", trip);
+    *type = g_thermal_trip[trip];
+    return 0;
+}
+
+static int wmt_thz_get_trip_temp(struct thermal_zone_device *thz_dev, int trip,
+                        unsigned long *pv)
+{
+    wmt_tm_dprintk("[mtktspa_get_trip_temp] %d\n", trip);
+    *pv = g_trip_temp[trip];
+    return 0;
+}
+
+static int wmt_thz_get_crit_temp(struct thermal_zone_device *thz_dev,
+             unsigned long *pv)
+{
+    wmt_tm_dprintk("[%s]\n", __func__);
+#define WMT_TM_TEMP_CRIT 85000 /* 85.000 degree Celsius */
+    *pv = WMT_TM_TEMP_CRIT;
+
+    return 0;
+}
+
+/* +mtktspa_cooling_sysrst_ops+ */
+static int wmt_cl_get_max_state(struct thermal_cooling_device *cool_dev,
+             unsigned long *pv)
+{
+    *pv = 1;
+    wmt_tm_dprintk("[%s] %d\n", __func__, *pv);
+       return 0;
+}
+
+static int wmt_cl_get_cur_state(struct thermal_cooling_device *cool_dev,
+             unsigned long *pv)
+{
+    *pv = cl_dev_state;
+    wmt_tm_dprintk("[%s] %d\n", __func__, *pv);
+       return 0;
+}
+
+static int wmt_cl_set_cur_state(struct thermal_cooling_device *cool_dev,
+             unsigned long v)
+{
+    wmt_tm_dprintk("[%s] %d\n", __func__, v);
+    cl_dev_state = v;
+
+    if (cl_dev_state == 1) {
+        //the temperature is over than the critical, system reboot.
+        BUG();
+    }
+
+    return 0;
+}
+/* -mtktspa_cooling_sysrst_ops- */
+
+static int wmt_send_signal(int level)
+{
+       int ret = 0;
+       int thro = level;
+
+       if (tm_input_pid == 0) {
+               wmt_tm_dprintk("[%s] pid is empty\n", __func__);
+               ret = -1;
+       }
+
+       wmt_tm_printk("[%s] pid is %d, %d, %d\n", __func__, tm_pid, tm_input_pid, thro);
+
+       if (ret == 0 && tm_input_pid != tm_pid) {
+               tm_pid = tm_input_pid;
+               pg_task = get_pid_task(find_vpid(tm_pid), PIDTYPE_PID);
+       }
+
+       if (ret == 0 && pg_task) {
+               siginfo_t info;
+               info.si_signo = SIGIO;
+               info.si_errno = 0;
+               info.si_code = thro;
+               info.si_addr = NULL;
+               ret = send_sig_info(SIGIO, &info, pg_task);
+       }
+
+       if (ret != 0) wmt_tm_info("[%s] ret=%d\n", __func__, ret);
+
+       return ret;
+}
+
+#define UNK_STAT -1
+#define LOW_STAT 0
+#define MID_STAT 1
+#define HIGH_STAT 2
+#define WFD_STAT 3
+
+static inline unsigned long thro(unsigned long a, unsigned int b, unsigned int c) {
+
+       unsigned long tmp;
+
+       tmp = (a << 10) * b / c;
+
+       return tmp >> 10;
+}
+
+static int wmt_judge_throttling(int index, int is_on, int interval)
+{
+       /*
+        *     throttling_stat
+        *        2 ( pa1=1,pa2=1 )
+        * UPPER ----
+        *        1 ( pa1=1,pa2=0 )
+        * LOWER ----
+        *        0 ( pa1=0,pa2=0 )
+        */
+       static unsigned int throttling_pre_stat = 0;
+       static int mail_box[2] = {-1,-1};
+
+       static bool is_reset = false;
+
+       unsigned long cur_thro = tx_throughput;
+       static unsigned long thro_constraint = 99 * 1000;
+
+       int cur_wifi_stat = 0;
+
+       wmt_tm_dprintk("[%s]+ [0]=%d, [1]=%d || [%d] is %s\n", __func__, mail_box[0], mail_box[1],
+                                                                                       index, (is_on==1?"ON":"OFF"));
+       mail_box[index] = is_on;
+
+       if (mail_box[0] >= 0 && mail_box[1] >= 0) {
+               cur_wifi_stat = mail_box[0] + mail_box[1];
+
+               /*
+                * If Wifi-display is on, go to WFD_STAT state, and reset the throttling.
+                */
+               if (tm_wfd_stat == 2)
+                       cur_wifi_stat = WFD_STAT;
+
+               switch(cur_wifi_stat) {
+                       case WFD_STAT:
+                               if (throttling_pre_stat != WFD_STAT) {
+                                       /*
+                                        * Enter Wifi-Display status, reset all throttling. Dont affect the performance of Wifi-Display.
+                                        */
+                                       wmt_send_signal(-1);
+                                       below_low_time = 0;
+                                       over_up_time = 0;
+                                       throttling_pre_stat = WFD_STAT;
+                                       wmt_tm_printk("WFD is on, reset everything!");
+                               }
+                       break;
+
+                       case HIGH_STAT:
+                               if (throttling_pre_stat < HIGH_STAT || throttling_pre_stat == WFD_STAT) {
+                                       if (cur_thro > 0) /*Wifi is working!!*/
+                                               thro_constraint = thro(cur_thro, up_numerator, up_denominator);
+                                       else /*At this moment, current throughput is none. Use the previous constraint.*/
+                                               thro_constraint = thro(thro_constraint, up_numerator, up_denominator);
+
+                                       wmt_tm_printk("LOW/MID-->HIGH:%lu <- (%d / %d) %lu", thro_constraint, up_numerator, up_denominator, cur_thro);
+
+                                       wmt_send_signal( thro_constraint/1000 );
+                                       throttling_pre_stat = HIGH_STAT;
+                                       over_up_time = 0;
+                               } else if (throttling_pre_stat == HIGH_STAT) {
+                                       over_up_time++;
+                                       if ( (over_up_time * interval) >= up_duration) {
+                                               if (cur_thro < thro_constraint) /*real throughput may have huge variant*/
+                                                       thro_constraint = thro(cur_thro, up_numerator, up_denominator);
+                                               else /* current throughput is large than constraint. WHAT!!!*/
+                                                       thro_constraint = thro(thro_constraint, up_numerator, up_denominator);
+
+                                               wmt_tm_printk("HIGH-->HIGH:%lu <- (%d / %d) %lu", thro_constraint, up_numerator, up_denominator, cur_thro);
+
+                                               wmt_send_signal( thro_constraint/1000 );
+                                               over_up_time = 0;
+                                       }
+                               } else {
+                                       wmt_tm_info("[%s] Error state1!!\n", __func__, throttling_pre_stat);
+                               }
+                               wmt_tm_printk("case2 time=%d\n", over_up_time);
+                       break;
+
+                       case MID_STAT:
+                               if (throttling_pre_stat == LOW_STAT) {
+                                       below_low_time = 0;
+                                       throttling_pre_stat = MID_STAT;
+                                       wmt_tm_printk("[%s] Go up!!\n", __func__);
+                               } else if (throttling_pre_stat == HIGH_STAT) {
+                                       over_up_time = 0;
+                                       throttling_pre_stat = MID_STAT;
+                                       wmt_tm_printk("[%s] Go down!!\n", __func__);
+                               } else {
+                                       throttling_pre_stat = MID_STAT;
+                                       wmt_tm_dprintk("[%s] pre_stat=%d!!\n", __func__, throttling_pre_stat);
+                               }
+                       break;
+
+                       case LOW_STAT:
+                               if (throttling_pre_stat == WFD_STAT) {
+                                       throttling_pre_stat = LOW_STAT;
+                                       wmt_tm_dprintk("[%s] pre_stat=%d!!\n", __func__, throttling_pre_stat);
+                               } else if (throttling_pre_stat > LOW_STAT) {
+                                       if (cur_thro < 5000 && cur_thro > 0) {
+                                               thro_constraint = cur_thro * 3;
+                                       } else if (cur_thro >= 5000) {
+                                               thro_constraint = thro(cur_thro, low_numerator, low_denominator);
+                                       } else {
+                                               thro_constraint = thro(thro_constraint, low_numerator, low_denominator);
+                                       }
+
+                                       wmt_tm_printk("MID/HIGH-->LOW:%lu <- (%d / %d) %lu", thro_constraint, low_numerator, low_denominator, cur_thro);
+                                       wmt_send_signal( thro_constraint/1000 );
+                                       throttling_pre_stat = LOW_STAT;
+                                       below_low_time = 0;
+                                       low_rst_time = 0;
+                                       is_reset = false;
+                               } else if (throttling_pre_stat == LOW_STAT) {
+                                       below_low_time++;
+                                       if ( (below_low_time*interval) >= low_duration) {
+                                               if (low_rst_time >= low_rst_max && !is_reset) {
+                                                       wmt_tm_printk("over rst time=%d", low_rst_time);
+
+                                                       wmt_send_signal(-1); //reset
+                                                       low_rst_time = low_rst_max;
+                                                       is_reset = true;
+                                               } else if(!is_reset) {
+                                                       if (cur_thro < 5000 && cur_thro > 0) {
+                                                               thro_constraint = cur_thro * 3;
+                                                       } else if (cur_thro >= 5000) {
+                                                               thro_constraint = thro(cur_thro, low_numerator, low_denominator);
+                                                               low_rst_time++;
+                                                       } else {
+                                                               thro_constraint = thro(thro_constraint, low_numerator, low_denominator);
+                                                               low_rst_time++;
+                                                       }
+
+                                                       wmt_tm_printk("LOW-->LOW:%lu <-(%d / %d) %lu", thro_constraint, low_numerator, low_denominator, cur_thro);
+
+                                                       wmt_send_signal( thro_constraint/1000 );
+                                                       below_low_time = 0;
+                                               } else {
+                                                       wmt_tm_dprintk("Have reset, no control!!");
+                                               }
+                                       }
+                               } else {
+                                       wmt_tm_info("[%s] Error state3 %d!!\n", __func__, throttling_pre_stat);
+                               }
+                               wmt_tm_dprintk("case0 time=%d, rst=%d %d\n", below_low_time, low_rst_time, is_reset);
+                       break;
+
+                       default:
+                               wmt_tm_info("[%s] Error cur_wifi_stat=%d!!\n", __func__, cur_wifi_stat);
+                       break;
+               }
+
+               mail_box[0] = UNK_STAT;
+               mail_box[1] = UNK_STAT;
+       } else {
+               wmt_tm_dprintk("[%s] dont get all info!!\n", __func__);
+       }
+       return 0;
+}
+
+/* +mtktspa_cooling_pa1_ops+ */
+static int wmt_cl_pa1_get_max_state(struct thermal_cooling_device *cool_dev,
+             unsigned long *pv)
+{
+    *pv = 1;
+    wmt_tm_dprintk("[%s] %d\n", __func__, *pv);
+    return 0;
+}
+
+static int wmt_cl_pa1_get_cur_state(struct thermal_cooling_device *cool_dev,
+             unsigned long *pv)
+{
+    *pv = cl_pa1_dev_state;
+    wmt_tm_dprintk("[%s] %d\n", __func__, *pv);
+    return 0;
+}
+
+static int wmt_cl_pa1_set_cur_state(struct thermal_cooling_device *cool_dev,
+             unsigned long v)
+{
+       struct linux_thermal_ctrl_if *p_linux_if = 0;
+       int ret = 0;
+
+       wmt_tm_dprintk("[%s] %d\n", __func__, v);
+
+       if (pg_wmt_tm) {
+               p_linux_if = &pg_wmt_tm->linux_if;
+       } else {
+               ret = -1;
+       }
+
+       cl_pa1_dev_state = (unsigned int)v;
+
+       if (cl_pa1_dev_state == 1) {
+               ret = wmt_judge_throttling(0, 1, p_linux_if->interval/1000);
+       } else {
+               ret = wmt_judge_throttling(0, 0, p_linux_if->interval/1000);
+       }
+       if (ret != 0) wmt_tm_info("[%s] ret=%d\n", __func__, ret);
+    return ret;
+}
+/* -mtktspa_cooling_pa1_ops- */
+
+/* +mtktspa_cooling_pa2_ops+ */
+static int wmt_cl_pa2_get_max_state(struct thermal_cooling_device *cool_dev,
+             unsigned long *pv)
+{
+    *pv = 1;
+    wmt_tm_dprintk("[%s] %d\n", __func__, *pv);
+    return 0;
+}
+
+static int wmt_cl_pa2_get_cur_state(struct thermal_cooling_device *cool_dev,
+             unsigned long *pv)
+{
+    *pv = cl_pa2_dev_state;
+    wmt_tm_dprintk("[%s] %d\n", __func__, *pv);
+    return 0;
+}
+
+static int wmt_cl_pa2_set_cur_state(struct thermal_cooling_device *cool_dev,
+             unsigned long v)
+{
+       struct linux_thermal_ctrl_if *p_linux_if = 0;
+       int ret = 0;
+
+       wmt_tm_dprintk("[%s] %d\n", __func__, v);
+
+       if (pg_wmt_tm) {
+               p_linux_if = &pg_wmt_tm->linux_if;
+       } else {
+               ret = -1;
+       }
+
+       cl_pa2_dev_state = (unsigned int)v;
+
+       if (cl_pa2_dev_state == 1) {
+               ret = wmt_judge_throttling(1, 1, p_linux_if->interval/1000);
+       } else {
+               ret = wmt_judge_throttling(1, 0, p_linux_if->interval/1000);
+       }
+       if (ret != 0) wmt_tm_info("[%s] ret=%d\n", __func__, ret);
+       return ret;
+}
+/* -mtktspa_cooling_pa2_ops- */
+
+#ifdef NEVER
+/* +mtktspa_cooling_pa3_ops+ */
+static int wmt_cl_pa3_get_max_state(struct thermal_cooling_device *cool_dev,
+             unsigned long *pv)
+{
+    *pv = 1;
+    wmt_tm_dprintk("[%s] %d\n", __func__, *pv);
+       return 0;
+}
+
+static int wmt_cl_pa3_get_cur_state(struct thermal_cooling_device *cool_dev,
+             unsigned long *pv)
+{
+    *pv = cl_pa3_dev_state;
+    wmt_tm_dprintk("[%s] %d\n", __func__, *pv);
+       return 0;
+}
+
+static int wmt_cl_pa3_set_cur_state(struct thermal_cooling_device *cool_dev,
+             unsigned long v)
+{
+       struct linux_thermal_ctrl_if *p_linux_if = 0;
+       int ret = 0;
+
+       wmt_tm_dprintk("[%s] %d\n", __func__, v);
+
+       if (pg_wmt_tm) {
+               p_linux_if = &pg_wmt_tm->linux_if;
+       } else {
+               ret = -1;
+       }
+
+       cl_pa3_dev_state = (unsigned int)v;
+
+       if (cl_pa3_dev_state == 1) {
+               //ret = wmt_arbitrate_thro(2,3);
+       } else {
+               //ret = wmt_arbitrate_thro(2,0);
+       }
+       if (ret != 0) wmt_tm_printk("[%s] ret=%d\n", __func__, ret);
+       return ret;
+}
+/* -mtktspa_cooling_pa3_ops- */
+#endif /* NEVER */
+
+int wmt_wifi_tx_thro_read( char *buf, char **start, off_t offset, int count, int *eof, void *data )
+{
+       count = sprintf(buf, "%lu\n", tx_throughput);
+
+       wmt_tm_dprintk("[%s] tx=%lu\n", __func__, tx_throughput);
+
+       return count;
+}
+
+/*New Wifi throttling Algo+*/
+ssize_t wmt_wifi_algo_write( struct file *filp, const char __user *buf, unsigned long len, void *data )
+{
+       char desc[MAX_LEN] = {0};
+
+       unsigned int tmp_up_dur = 30;
+       unsigned int tmp_up_den = 2;
+       unsigned int tmp_up_num = 1;
+
+       unsigned int tmp_low_dur = 3;
+       unsigned int tmp_low_den = 2;
+       unsigned int tmp_low_num = 3;
+
+       unsigned int tmp_low_rst_max = 3;
+
+       unsigned int tmp_log = 0;
+
+       len = (len < (sizeof(desc) - 1)) ? len : (sizeof(desc) - 1);
+
+       /* write data to the buffer */
+       if (copy_from_user(desc, buf, len)) {
+               return -EFAULT;
+       }
+
+       if (sscanf(desc, "%d %d/%d, %d %d/%d, %d", &tmp_up_dur, &tmp_up_num, &tmp_up_den, &tmp_low_dur, \
+                                                               &tmp_low_num, &tmp_low_den, &tmp_low_rst_max) == 7) {
+
+               up_duration = tmp_up_dur;
+               up_denominator = tmp_up_den;
+               up_numerator = tmp_up_num;
+
+               low_duration = tmp_low_dur;
+               low_denominator = tmp_low_den;
+               low_numerator = tmp_low_num;
+
+               low_rst_max = tmp_low_rst_max;
+
+               over_up_time = 0;
+               below_low_time = 0;
+               low_rst_time = 0;
+
+               wmt_tm_printk("[%s] %s [up]%d %d/%d, [low]%d %d/%d, rst=%d\n", __func__, desc, up_duration, \
+                       up_numerator, up_denominator, low_duration, low_numerator, low_denominator, low_rst_max);
+
+               return len;
+       } else if (sscanf(desc, "log=%d", &tmp_log) == 1) {
+               if (tmp_log == 1)
+                       wmt_tm_debug_log = 1;
+               else
+                       wmt_tm_debug_log = 0;
+
+               return len;
+       } else {
+               wmt_tm_printk("[%s] bad argument = %s\n", __func__, desc);
+       }
+    return -EINVAL;
+}
+
+int wmt_wifi_algo_read( char *buf, char **start, off_t offset, int count, int *eof, void *data )
+{
+       int ret;
+       char tmp[MAX_LEN] = {0};
+
+       sprintf(tmp, "[up]\t%3d(sec)\t%2d/%2d\n[low]\t%3d(sec)\t%2d/%2d\nrst=%2d\n", up_duration, up_numerator, up_denominator, \
+                                                               low_duration, low_numerator, low_denominator, low_rst_max);
+       ret = strlen(tmp);
+
+       memcpy(buf, tmp, ret*sizeof(char));
+
+       wmt_tm_printk("[%s] [up]%d %d/%d, [low]%d %d/%d, rst=%d\n", __func__, up_duration, \
+               up_numerator, up_denominator, low_duration, low_numerator, low_denominator, low_rst_max);
+
+       return ret;
+}
+/*New Wifi throttling Algo-*/
+
+ssize_t wmt_tm_wfd_write( struct file *filp, const char __user *buf, unsigned long len, void *data )
+{
+       int ret = 0;
+       char tmp[MAX_LEN] = {0};
+
+       /* write data to the buffer */
+       if (copy_from_user(tmp, buf, len)) {
+               return -EFAULT;
+    }
+
+       ret = sscanf(tmp, "%d", &tm_wfd_stat);
+
+       wmt_tm_printk("[%s] %s = %d, len=%d, ret=%d\n", __func__, tmp, tm_wfd_stat, len, ret);
+
+               return len;
+}
+
+int wmt_tm_wfd_read( char *buf, char **start, off_t offset , int count, int *eof, void *data )
+{
+       int len;
+       int ret = 0;
+       char tmp[MAX_LEN] = {0};
+
+       ret = sprintf(tmp, "%d", tm_wfd_stat);
+       len = strlen(tmp);
+
+       memcpy(buf, tmp, ret*sizeof(char));
+
+       wmt_tm_printk("[%s] %s = %d, len=%d, ret=%d\n", __func__, tmp, tm_wfd_stat, len, ret);
+
+       return ret;
+}
+
+ssize_t wmt_tm_pid_write( struct file *filp, const char __user *buf, unsigned long len, void *data )
+{
+       int ret = 0;
+       char tmp[MAX_LEN] = {0};
+
+       /* write data to the buffer */
+       if ( copy_from_user(tmp, buf, len) ) {
+               return -EFAULT;
+       }
+
+       ret = kstrtouint(tmp, 10, &tm_input_pid);
+       if (ret)
+               WARN_ON(1);
+
+       wmt_tm_printk("[%s] %s = %d\n", __func__, tmp, tm_input_pid);
+
+       return len;
+}
+
+int wmt_tm_pid_read( char *buf, char **start, off_t offset , int count, int *eof, void *data )
+{
+       int ret;
+       char tmp[MAX_LEN] = {0};
+
+       sprintf(tmp, "%d", tm_input_pid);
+       ret = strlen(tmp);
+
+       memcpy(buf, tmp, ret*sizeof(char));
+
+       wmt_tm_printk("[%s] %s = %d\n", __func__, buf, tm_input_pid);
+
+       return ret;
+}
+
+#define check_str(x) (x[0]=='\0'?"none\t":x)
+
+static int wmt_tm_read(char *buf, char **start, off_t off, int count, int *eof, void *data)
+{
+    int len = 0;
+    char *p = buf;
+    struct linux_thermal_ctrl_if *p_linux_if = 0;
+
+    wmt_tm_printk("[%s]\n", __func__);
+
+    //sanity
+    if(pg_wmt_tm) {
+       p_linux_if = &pg_wmt_tm->linux_if;
+    } else {
+       wmt_tm_info("[wmt_tm_read] fail! \n");
+       return -EINVAL;
+    }
+
+    p += sprintf(p, "[wmt_tm_read]"\
+                    "\n \tcooler\t\ttrip_temp\ttrip_type" \
+                    "\n [0] %s\t%d\t\t%d" \
+                    "\n [1] %s\t%d\t\t%d" \
+                    "\n [2] %s\t%d\t\t%d" \
+                    "\n [3] %s\t%d\t\t%d" \
+                    "\n [4] %s\t%d\t\t%d" \
+                    "\n [5] %s\t%d\t\t%d" \
+                    "\n [6] %s\t%d\t\t%d" \
+                    "\n [7] %s\t%d\t\t%d" \
+                    "\n [8] %s\t%d\t\t%d" \
+                    "\n [9] %s\t%d\t\t%d" \
+                    "\ntime_ms=%d\n", \
+                    check_str(g_bind0),g_trip_temp[0],g_thermal_trip[0], check_str(g_bind1),g_trip_temp[1],g_thermal_trip[1],\
+                    check_str(g_bind2),g_trip_temp[2],g_thermal_trip[2], check_str(g_bind3),g_trip_temp[3],g_thermal_trip[3],\
+                    check_str(g_bind4),g_trip_temp[4],g_thermal_trip[4], check_str(g_bind5),g_trip_temp[5],g_thermal_trip[5],\
+                    check_str(g_bind6),g_trip_temp[6],g_thermal_trip[6], check_str(g_bind7),g_trip_temp[7],g_thermal_trip[7],\
+                    check_str(g_bind8),g_trip_temp[8],g_thermal_trip[8], check_str(g_bind9),g_trip_temp[9],g_thermal_trip[9],\
+                    p_linux_if->interval);
+
+    *start = buf + off;
+
+    len = p - buf;
+    if (len > off)
+        len -= off;
+    else
+        len = 0;
+
+    return len < count ? len  : count;
+}
+
+static ssize_t wmt_tm_write(struct file *file, const char *buffer, unsigned long count, void *data)
+{
+    int i = 0;
+    int len=0,time_msec=0;
+    int trip_temp[COOLER_NUM] = {0};
+    int thermal_trip[COOLER_NUM] = {0};
+
+    char desc[512];
+    char bind0[20],bind1[20],bind2[20],bind3[20],bind4[20];
+    char bind5[20],bind6[20],bind7[20],bind8[20],bind9[20];
+
+    struct linux_thermal_ctrl_if *p_linux_if = 0;
+
+    wmt_tm_printk("[%s]\n", __func__);
+
+    //sanity
+    if(pg_wmt_tm) {
+       p_linux_if = &pg_wmt_tm->linux_if;
+    } else {
+       wmt_tm_info("[wmt_thz_write] fail! \n");
+       return -EINVAL;
+    }
+
+    len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1);
+
+    if (copy_from_user(desc, buffer, len)) {
+        return 0;
+    }
+
+    desc[len] = '\0';
+
+    if (sscanf(desc, "%d %d %d %s %d %d %s %d %d %s %d %d %s %d %d %s %d %d %s %d %d %s %d %d %s %d %d %s %d %d %s %d",
+                      &g_num_trip, &trip_temp[0], &thermal_trip[0], bind0,
+                      &trip_temp[1], &thermal_trip[1], bind1,
+                      &trip_temp[2], &thermal_trip[2], bind2,
+                      &trip_temp[3], &thermal_trip[3], bind3,
+                      &trip_temp[4], &thermal_trip[4], bind4,
+                      &trip_temp[5], &thermal_trip[5], bind5,
+                      &trip_temp[6], &thermal_trip[6], bind6,
+                      &trip_temp[7], &thermal_trip[7], bind7,
+                      &trip_temp[8], &thermal_trip[8], bind8,
+                      &trip_temp[9], &thermal_trip[9], bind9,
+                      &time_msec) == 32)
+    {
+        // unregister
+        if (p_linux_if->thz_dev) {
+               mtk_thermal_zone_device_unregister(p_linux_if->thz_dev);
+               p_linux_if->thz_dev = NULL;
+       }
+
+               for ( i = 0; i < g_num_trip; i++) {
+                       g_thermal_trip[i] = thermal_trip[i];
+               }
+
+               g_bind0[0]=g_bind1[0]=g_bind2[0]=g_bind3[0]=g_bind4[0]='\0';
+               g_bind5[0]=g_bind6[0]=g_bind7[0]=g_bind8[0]=g_bind9[0]='\0';
+
+               for ( i = 0; i < 20; i++ ) {
+                       g_bind0[i]=bind0[i];
+                       g_bind1[i]=bind1[i];
+                       g_bind2[i]=bind2[i];
+                       g_bind3[i]=bind3[i];
+                       g_bind4[i]=bind4[i];
+                       g_bind5[i]=bind5[i];
+                       g_bind6[i]=bind6[i];
+                       g_bind7[i]=bind7[i];
+                       g_bind8[i]=bind8[i];
+                       g_bind9[i]=bind9[i];
+               }
+
+               for ( i = 0; i < g_num_trip; i++) {
+                       g_trip_temp[i] = trip_temp[i];
+               }
+
+        p_linux_if->interval = time_msec;
+
+        wmt_tm_printk("[wmt_tm_write] g_trip_temp [0]=%d, [1]=%d, [2]=%d, [3]=%d, [4]=%d\n",
+                       g_thermal_trip[0], g_thermal_trip[1], g_thermal_trip[2],
+                       g_thermal_trip[3], g_thermal_trip[4]);
+
+        wmt_tm_printk("[wmt_tm_write] g_trip_temp [5]=%d, [6]=%d, [7]=%d, [8]=%d, [9]=%d\n",
+                       g_thermal_trip[5], g_thermal_trip[6], g_thermal_trip[7],
+                       g_thermal_trip[8], g_thermal_trip[9]);
+
+        wmt_tm_printk("[wmt_tm_write] cooldev [0]=%s, [1]=%s, [2]=%s, [3]=%s, [4]=%s,\n",
+                       g_bind0, g_bind1, g_bind2, g_bind3, g_bind4);
+
+        wmt_tm_printk("[wmt_tm_write] cooldev [5]=%s, [6]=%s, [7]=%s, [8]=%s, [9]=%s,\n",
+                       g_bind5, g_bind6, g_bind7, g_bind8, g_bind9);
+
+        wmt_tm_printk("[wmt_tm_write] trip_temp [0]=%d, [1]=%d, [2]=%d, [3]=%d, [4]=%d\n",
+                       trip_temp[0], trip_temp[1], trip_temp[2], trip_temp[3], trip_temp[4]);
+
+        wmt_tm_printk("[wmt_tm_write] trip_temp [5]=%d, [6]=%d, [7]=%d, [8]=%d, [9]=%d\n",
+                       trip_temp[5], trip_temp[6], trip_temp[7], trip_temp[8], trip_temp[9]);
+
+        wmt_tm_printk("[wmt_tm_write] polling time=%d\n", p_linux_if->interval);
+
+        //p_linux_if->thz_dev->polling_delay = p_linux_if->interval*1000;
+
+        //thermal_zone_device_update(p_linux_if->thz_dev);
+
+        // register
+        p_linux_if->thz_dev = mtk_thermal_zone_device_register("mtktswmt", g_num_trip, NULL,
+                                &wmt_thz_dev_ops, 0, 0, 0, p_linux_if->interval);
+
+        wmt_tm_printk("[wmt_tm_write] time_ms=%d\n", p_linux_if->interval);
+
+        return count;
+    } else {
+        wmt_tm_info("[%s] bad argument = %s\n", __func__, desc);
+    }
+
+    return -EINVAL;
+}
+
+static int wmt_tm_proc_register(void)
+{
+    struct proc_dir_entry *entry = NULL;
+    struct proc_dir_entry *wmt_tm_proc_dir = NULL;
+
+    wmt_tm_printk("[%s]\n", __func__);
+
+    wmt_tm_proc_dir = proc_mkdir("wmt_tm", NULL);
+    if (!wmt_tm_proc_dir) {
+        wmt_tm_printk("[wmt_tm_proc_register]: mkdir /proc/wmt_tm failed\n");
+    } else {
+        entry = create_proc_entry("wmt_tm", S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, wmt_tm_proc_dir);
+        if (entry) {
+            entry->read_proc = wmt_tm_read;
+            entry->write_proc = wmt_tm_write;
+        }
+
+        entry = create_proc_entry("tm_pid", S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, wmt_tm_proc_dir);
+        if (entry) {
+            entry->read_proc = wmt_tm_pid_read;
+            entry->write_proc = wmt_tm_pid_write;
+        }
+
+        entry = create_proc_entry("wmt_val", S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, wmt_tm_proc_dir);
+        if (entry) {
+            entry->read_proc = wmt_wifi_algo_read;
+            entry->write_proc = wmt_wifi_algo_write;
+        }
+
+        entry = create_proc_entry("tx_thro", S_IRUGO | S_IWUSR, wmt_tm_proc_dir);
+        if (entry) {
+            entry->read_proc = wmt_wifi_tx_thro_read;
+        }
+
+        entry = create_proc_entry("wfd_stat", S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, wmt_tm_proc_dir);
+        if (entry) {
+            entry->read_proc = wmt_tm_wfd_read;
+            entry->write_proc = wmt_tm_wfd_write;
+        }
+    }
+    return 0;
+}
+
+static int wmt_tm_proc_unregister(void)
+{
+    wmt_tm_printk("[%s]\n", __func__);
+    //remove_proc_entry("wmt_tm", proc_entry);
+    return 0;
+}
+
+static int wmt_tm_thz_cl_register(void)
+{
+    #define DEFAULT_POLL_TIME 0 /*Default disable, turn on by thermal policy*/
+
+    struct linux_thermal_ctrl_if *p_linux_if = 0;
+
+       wmt_tm_printk("[%s]\n", __func__);
+
+    if(pg_wmt_tm) {
+       p_linux_if = &pg_wmt_tm->linux_if;
+    } else {
+       return -1;
+    }
+
+    /* cooling devices */
+    p_linux_if->cl_dev = mtk_thermal_cooling_device_register("mtktswmt-sysrst", NULL,
+                           &mtktspa_cooling_sysrst_ops);
+
+    p_linux_if->cl_pa1_dev = mtk_thermal_cooling_device_register("mtktswmt-pa1", NULL,
+                           &mtktspa_cooling_pa1_ops);
+
+    p_linux_if->cl_pa2_dev = mtk_thermal_cooling_device_register("mtktswmt-pa2", NULL,
+                           &mtktspa_cooling_pa2_ops);
+
+#ifdef NEVER
+    p_linux_if->cl_pa3_dev = mtk_thermal_cooling_device_register("mtktswmt-pa3", NULL,
+                           &mtktspa_cooling_pa3_ops);
+#endif /* NEVER */
+
+       p_linux_if->interval = DEFAULT_POLL_TIME;
+
+    /* trips */
+    p_linux_if->thz_dev = mtk_thermal_zone_device_register("mtktswmt", g_num_trip, NULL,
+                           &wmt_thz_dev_ops, 0, 0, 0, p_linux_if->interval);
+
+    return 0;
+}
+
+static int wmt_tm_thz_cl_unregister(void)
+{
+    struct linux_thermal_ctrl_if *p_linux_if = 0;
+
+    wmt_tm_printk("[%s]\n", __func__);
+
+    if(pg_wmt_tm) {
+       p_linux_if = &pg_wmt_tm->linux_if;
+    } else {
+       return -1;
+    }
+
+    if (p_linux_if->cl_dev) {
+        mtk_thermal_cooling_device_unregister(p_linux_if->cl_dev);
+        p_linux_if->cl_dev = NULL;
+    }
+
+    if (p_linux_if->cl_pa1_dev) {
+        mtk_thermal_cooling_device_unregister(p_linux_if->cl_pa1_dev);
+        p_linux_if->cl_pa1_dev = NULL;
+    }
+
+    if (p_linux_if->cl_pa2_dev) {
+        mtk_thermal_cooling_device_unregister(p_linux_if->cl_pa2_dev);
+        p_linux_if->cl_pa2_dev = NULL;
+    }
+
+#ifdef NEVER
+    if (p_linux_if->cl_pa3_dev) {
+        mtk_thermal_cooling_device_unregister(p_linux_if->cl_pa3_dev);
+        p_linux_if->cl_pa3_dev = NULL;
+    }
+#endif /* NEVER */
+
+    if (p_linux_if->thz_dev) {
+        mtk_thermal_zone_device_unregister(p_linux_if->thz_dev);
+        p_linux_if->thz_dev = NULL;
+    }
+
+    return 0;
+}
+
+static int wmt_tm_ops_register(struct wmt_thermal_ctrl_ops *ops)
+{
+    struct wmt_thermal_ctrl_ops *p_des;
+
+   wmt_tm_printk("[%s]\n", __func__);
+
+    if (pg_wmt_tm) {
+#if 1
+        p_des = &pg_wmt_tm->wmt_if.ops;
+        if (ops!=NULL) {
+            wmt_tm_printk("[wmt_tm_ops_register] reg start ...\n");
+            p_des->query_temp = ops->query_temp;
+            p_des->set_temp = ops->set_temp;
+            wmt_tm_printk("[wmt_tm_ops_register] reg end ...\n");
+        } else {
+            p_des->query_temp =  0;
+            p_des->set_temp = 0;
+        }
+#endif
+        return 0;
+    } else {
+        return -1;
+    }
+}
+
+static int wmt_tm_ops_unregister(void)
+{
+    struct wmt_thermal_ctrl_ops *p_des;
+
+   wmt_tm_printk("[%s]\n", __func__);
+
+    if (pg_wmt_tm) {
+        p_des = &pg_wmt_tm->wmt_if.ops;
+        p_des->query_temp = 0;
+        p_des->set_temp = 0;
+
+        return 0;
+    } else {
+        return -1;
+    }
+}
+
+int wmt_tm_init(struct wmt_thermal_ctrl_ops *ops)
+{
+    int err = 0;
+
+    wmt_tm_printk("[wmt_tm_init] start -->\n");
+
+    err = wmt_tm_ops_register(ops);
+    if(err)
+        return err;
+
+    err = wmt_tm_proc_register();
+    if(err)
+        return err;
+
+    /* init a timer for stats tx bytes */
+    wmt_stats_info.pre_time = 0;
+    wmt_stats_info.pre_tx_bytes = 0;
+
+    init_timer(&wmt_stats_timer);
+    wmt_stats_timer.function = (void *)&wmt_cal_stats;
+    wmt_stats_timer.data = (unsigned long) &wmt_stats_info;
+    wmt_stats_timer.expires = jiffies + 1 * HZ;
+    add_timer(&wmt_stats_timer);
+
+#if 0
+    err = wmt_tm_thz_cl_register();
+    if(err)
+        return err;
+#endif
+    wmt_tm_printk("[wmt_tm_init] end <--\n");
+
+    return 0;
+}
+
+int wmt_tm_init_rt()
+{
+    int err = 0;
+
+    wmt_tm_printk("[wmt_tm_init_rt] start -->\n");
+
+    err = wmt_tm_thz_cl_register();
+    if(err)
+        return err;
+
+    wmt_tm_printk("[wmt_tm_init_rt] end <--\n");
+
+    return 0;
+}
+
+int wmt_tm_deinit_rt()
+{
+    int err = 0;
+
+    wmt_tm_printk("[wmt_tm_deinit_rt] start -->\n");
+
+    err = wmt_tm_thz_cl_unregister();
+    if(err)
+        return err;
+
+    wmt_tm_printk("[wmt_tm_deinit_rt] end <--\n");
+
+    return 0;
+}
+
+int wmt_tm_deinit()
+{
+    int err = 0;
+
+    wmt_tm_printk("[%s]\n", __func__);
+#if 0
+    err = wmt_tm_thz_cl_unregister();
+    if(err)
+        return err;
+#endif
+    err = wmt_tm_proc_unregister();
+    if(err)
+        return err;
+
+    err = wmt_tm_ops_unregister();
+    if(err)
+        return err;
+
+    del_timer(&wmt_stats_timer);
+
+    return 0;
+}
+#endif
+#endif
+
diff --git a/drivers/mtk_wcn_combo/common/platform/rockchip/mtk_wcn_cmb_hw.c b/drivers/mtk_wcn_combo/common/platform/rockchip/mtk_wcn_cmb_hw.c
new file mode 100755 (executable)
index 0000000..980ef58
--- /dev/null
@@ -0,0 +1,346 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ *
+ * MediaTek Inc. (C) 2010. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+
+
+/*! \file
+    \brief  Declaration of library functions
+
+    Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+/*******************************************************************************
+* Copyright (c) 2009 MediaTek Inc.
+*
+* All rights reserved. Copying, compilation, modification, distribution
+* or any other use whatsoever of this material is strictly prohibited
+* except in accordance with a Software License Agreement with
+* MediaTek Inc.
+********************************************************************************
+*/
+
+/*******************************************************************************
+* LEGAL DISCLAIMER
+*
+* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND
+* AGREES THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK
+* SOFTWARE") RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE
+* PROVIDED TO BUYER ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY
+* DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+* LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+* PARTICULAR PURPOSE OR NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE
+* ANY WARRANTY WHATSOEVER WITH RESPECT TO THE SOFTWARE OF ANY THIRD PARTY
+* WHICH MAY BE USED BY, INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK
+* SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY
+* WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE
+* FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S SPECIFICATION OR TO
+* CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL
+* BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT
+* ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY
+* BUYER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT
+* OF LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING
+* THEREOF AND RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN
+* FRANCISCO, CA, UNDER THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE
+* (ICC).
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+*                         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-CMB-HW]"
+
+
+/*******************************************************************************
+*                    E X T E R N A L   R E F E R E N C E S
+********************************************************************************
+*/
+#include "osal.h"
+#include "mtk_wcn_cmb_hw.h"
+#include "wmt_plat.h"
+#include "wmt_exp.h"
+
+/*******************************************************************************
+*                              C O N S T A N T S
+********************************************************************************
+*/
+#define DFT_RTC_STABLE_TIME 100
+#define DFT_LDO_STABLE_TIME 100
+#define DFT_RST_STABLE_TIME 30
+#define DFT_OFF_STABLE_TIME 10
+#define DFT_ON_STABLE_TIME 30
+
+/*******************************************************************************
+*                             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
+********************************************************************************
+*/
+
+PWR_SEQ_TIME gPwrSeqTime;
+
+
+
+
+/*******************************************************************************
+*                  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_cmb_hw_pwr_off (VOID)
+{
+    INT32 iRet = 0;
+    WMT_INFO_FUNC("CMB-HW, hw_pwr_off start\n");
+
+    /*1. disable irq --> should be done when do wmt-ic swDeinit period*/
+    // TODO:[FixMe][GeorgeKuo] clarify this
+
+    /*2. set bgf eint/all eint to deinit state, namely input low state*/
+    iRet += wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_DEINIT);
+    iRet += wmt_plat_gpio_ctrl(PIN_BGF_EINT, PIN_STA_DEINIT);
+    WMT_INFO_FUNC("CMB-HW, BGF_EINT IRQ unregistered and set BGF_EINT GPIO to correct state!\n");
+    /* 2.1 set ALL_EINT pin to correct state even it is not used currently */
+    iRet += wmt_plat_eirq_ctrl(PIN_ALL_EINT, PIN_STA_EINT_DIS);
+    WMT_INFO_FUNC("CMB-HW, ALL_EINT IRQ unregistered and disabled\n");
+    iRet += wmt_plat_gpio_ctrl(PIN_ALL_EINT, PIN_STA_DEINIT);
+    /* 2.2 deinit gps sync */
+    iRet += wmt_plat_gpio_ctrl(PIN_GPS_SYNC, PIN_STA_DEINIT);
+
+    /*3. set audio interface to CMB_STUB_AIF_0, BT PCM OFF, I2S OFF*/
+    iRet += wmt_plat_audio_ctrl(CMB_STUB_AIF_0, CMB_STUB_AIF_CTRL_DIS);
+
+    /*4. set control gpio into deinit state, namely input low state*/
+    iRet += wmt_plat_gpio_ctrl(PIN_SDIO_GRP, PIN_STA_DEINIT);
+    iRet += wmt_plat_gpio_ctrl(PIN_RST, PIN_STA_OUT_L);
+    iRet += wmt_plat_gpio_ctrl(PIN_PMU, PIN_STA_OUT_L);
+
+    /*5. set uart tx/rx into deinit state, namely input low state*/
+    iRet += wmt_plat_gpio_ctrl(PIN_UART_GRP, PIN_STA_DEINIT);
+
+    /* 6. Last, LDO output low */
+    iRet += wmt_plat_gpio_ctrl(PIN_LDO, PIN_STA_OUT_L);
+    
+    /*7. deinit gps_lna*/
+    iRet += wmt_plat_gpio_ctrl(PIN_GPS_LNA, PIN_STA_DEINIT);
+    
+    WMT_INFO_FUNC("CMB-HW, hw_pwr_off finish\n");
+    return iRet;
+}
+
+INT32
+mtk_wcn_cmb_hw_pwr_on (VOID)
+{
+    static UINT32 _pwr_first_time = 1;
+    INT32 iRet = 0;
+
+    WMT_INFO_FUNC("CMB-HW, hw_pwr_on start\n");
+#if 0 //IRQ should in inact state before power on, so this step is not needed
+    /* disable interrupt firstly */
+    iRet += wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_EINT_DIS);
+    iRet += wmt_plat_eirq_ctrl(PIN_ALL_EINT, PIN_STA_EINT_DIS);
+#endif
+    /*set all control and eint gpio to init state, namely input low mode*/
+    iRet += wmt_plat_gpio_ctrl(PIN_LDO, PIN_STA_INIT);
+    iRet += wmt_plat_gpio_ctrl(PIN_PMU, PIN_STA_INIT);
+    iRet += wmt_plat_gpio_ctrl(PIN_RST, PIN_STA_INIT);
+    iRet += wmt_plat_gpio_ctrl(PIN_SDIO_GRP, PIN_STA_INIT);
+    iRet += wmt_plat_gpio_ctrl(PIN_BGF_EINT, PIN_STA_INIT);
+    iRet += wmt_plat_gpio_ctrl(PIN_ALL_EINT, PIN_STA_INIT);
+    iRet += wmt_plat_gpio_ctrl(PIN_GPS_SYNC, PIN_STA_INIT);
+    iRet += wmt_plat_gpio_ctrl(PIN_GPS_LNA, PIN_STA_INIT);
+    // wmt_plat_gpio_ctrl(PIN_WIFI_EINT, PIN_STA_INIT); /* WIFI_EINT is controlled by SDIO host driver */
+    // TODO: [FixMe][George]:WIFI_EINT is used in common SDIO
+
+    /*1. pull high LDO to supply power to chip*/
+    iRet += wmt_plat_gpio_ctrl(PIN_LDO, PIN_STA_OUT_H);
+    osal_msleep(gPwrSeqTime.ldoStableTime);
+
+    /* 2. export RTC clock to chip*/
+    if (_pwr_first_time) {
+        /* rtc clock should be output all the time, so no need to enable output again*/
+        iRet += wmt_plat_gpio_ctrl(PIN_RTC, PIN_STA_INIT);
+        osal_msleep(gPwrSeqTime.rtcStableTime);
+        WMT_INFO_FUNC("CMB-HW, rtc clock exported\n");
+    }
+
+    /*3. set UART Tx/Rx to UART mode*/
+    iRet += wmt_plat_gpio_ctrl(PIN_UART_GRP, PIN_STA_INIT);
+
+    /*4. PMU->output low, RST->output low, sleep off stable time*/
+    iRet += wmt_plat_gpio_ctrl(PIN_PMU, PIN_STA_OUT_L);
+    iRet += wmt_plat_gpio_ctrl(PIN_RST, PIN_STA_OUT_L);
+    osal_msleep(gPwrSeqTime.offStableTime);
+
+    /*5. PMU->output high, sleep rst stable time*/
+    iRet += wmt_plat_gpio_ctrl(PIN_PMU, PIN_STA_OUT_H);
+    osal_msleep(gPwrSeqTime.rstStableTime);
+
+    /*6. RST->output high, sleep on stable time*/
+    iRet += wmt_plat_gpio_ctrl(PIN_RST, PIN_STA_OUT_H);
+    osal_msleep(gPwrSeqTime.onStableTime);
+
+    /*7. set audio interface to CMB_STUB_AIF_1, BT PCM ON, I2S OFF*/
+    /* BT PCM bus default mode. Real control is done by audio */
+    iRet += wmt_plat_audio_ctrl(CMB_STUB_AIF_1, CMB_STUB_AIF_CTRL_DIS);
+
+    /*8. set EINT< -ommited-> move this to WMT-IC module, where common sdio interface will be identified and do proper operation*/
+    // 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_INFO_FUNC("CMB-HW, BGF_EINT IRQ registered and disabled \n");
+
+    /* 8.1 set ALL_EINT pin to correct state even it is not used currently */
+    iRet += wmt_plat_gpio_ctrl(PIN_ALL_EINT, PIN_STA_MUX);
+    iRet += wmt_plat_eirq_ctrl(PIN_ALL_EINT, PIN_STA_INIT);
+    iRet += wmt_plat_eirq_ctrl(PIN_ALL_EINT, PIN_STA_EINT_DIS);
+    WMT_INFO_FUNC("CMB-HW, hw_pwr_on finish (%d)\n", iRet);
+
+    _pwr_first_time = 0;
+    return iRet;
+
+}
+
+INT32
+mtk_wcn_cmb_hw_rst (VOID)
+{
+    INT32 iRet = 0;
+    WMT_INFO_FUNC("CMB-HW, hw_rst start, eirq should be disabled before this step\n");
+
+    /*1. PMU->output low, RST->output low, sleep off stable time*/
+    iRet += wmt_plat_gpio_ctrl(PIN_PMU, PIN_STA_OUT_L);
+    iRet += wmt_plat_gpio_ctrl(PIN_RST, PIN_STA_OUT_L);
+    osal_msleep(gPwrSeqTime.offStableTime);
+
+    /*2. PMU->output high, sleep rst stable time*/
+    iRet += wmt_plat_gpio_ctrl(PIN_PMU, PIN_STA_OUT_H);
+    osal_msleep(gPwrSeqTime.rstStableTime);
+
+    /*3. RST->output high, sleep on stable time*/
+    iRet += wmt_plat_gpio_ctrl(PIN_RST, PIN_STA_OUT_H);
+    osal_msleep(gPwrSeqTime.onStableTime);
+    WMT_INFO_FUNC("CMB-HW, hw_rst finish, eirq should be enabled after this step\n");
+    return 0;
+}
+
+static VOID
+mtk_wcn_cmb_hw_dmp_seq (VOID)
+{
+    PUINT32 pTimeSlot = (PUINT32)&gPwrSeqTime;
+    WMT_INFO_FUNC("combo chip power on sequence time, RTC (%d), LDO (%d), RST(%d), OFF(%d), ON(%d)\n",
+        pTimeSlot[0], /**pTimeSlot++,*/
+        pTimeSlot[1],
+        pTimeSlot[2],
+        pTimeSlot[3],
+        pTimeSlot[4]
+        );
+    return;
+}
+
+INT32
+mtk_wcn_cmb_hw_init (
+    P_PWR_SEQ_TIME pPwrSeqTime
+    )
+{
+    if (NULL != pPwrSeqTime            && 
+        pPwrSeqTime->ldoStableTime > 0 &&
+        pPwrSeqTime->rtcStableTime > 0 &&
+        pPwrSeqTime->offStableTime > DFT_OFF_STABLE_TIME &&
+        pPwrSeqTime->onStableTime  > DFT_ON_STABLE_TIME  &&
+        pPwrSeqTime->rstStableTime > DFT_RST_STABLE_TIME
+    ) {
+        /*memcpy may be more performance*/
+        WMT_DBG_FUNC("setting hw init sequence parameters\n");
+        osal_memcpy(&gPwrSeqTime, pPwrSeqTime, osal_sizeof(gPwrSeqTime));
+    }
+    else {    
+        WMT_WARN_FUNC("invalid pPwrSeqTime parameter, use default hw init sequence parameters\n");
+        gPwrSeqTime.ldoStableTime = DFT_LDO_STABLE_TIME;
+        gPwrSeqTime.offStableTime = DFT_OFF_STABLE_TIME;
+        gPwrSeqTime.onStableTime = DFT_ON_STABLE_TIME;
+        gPwrSeqTime.rstStableTime = DFT_RST_STABLE_TIME;
+        gPwrSeqTime.rtcStableTime = DFT_RTC_STABLE_TIME;
+    }
+    mtk_wcn_cmb_hw_dmp_seq();
+    return 0;
+}
+
+INT32
+mtk_wcn_cmb_hw_deinit (VOID)
+{
+
+    WMT_WARN_FUNC("mtk_wcn_cmb_hw_deinit start, set to default hw init sequence parameters\n");
+    gPwrSeqTime.ldoStableTime = DFT_LDO_STABLE_TIME;
+    gPwrSeqTime.offStableTime = DFT_OFF_STABLE_TIME;
+    gPwrSeqTime.onStableTime = DFT_ON_STABLE_TIME;
+    gPwrSeqTime.rstStableTime = DFT_RST_STABLE_TIME;
+    gPwrSeqTime.rtcStableTime = DFT_RTC_STABLE_TIME;
+    WMT_WARN_FUNC("mtk_wcn_cmb_hw_deinit finish\n");
+    return 0;
+}
+
diff --git a/drivers/mtk_wcn_combo/common/platform/rockchip/mtk_wcn_cmb_stub_rockchip.c b/drivers/mtk_wcn_combo/common/platform/rockchip/mtk_wcn_cmb_stub_rockchip.c
new file mode 100755 (executable)
index 0000000..69546c0
--- /dev/null
@@ -0,0 +1,348 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ *
+ * MediaTek Inc. (C) 2010. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+
+
+/*! \file
+    \brief  Declaration of library functions
+
+    Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+/*******************************************************************************
+* Copyright (c) 2009 MediaTek Inc.
+*
+* All rights reserved. Copying, compilation, modification, distribution
+* or any other use whatsoever of this material is strictly prohibited
+* except in accordance with a Software License Agreement with
+* MediaTek Inc.
+********************************************************************************
+*/
+
+/*******************************************************************************
+* LEGAL DISCLAIMER
+*
+* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND
+* AGREES THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK
+* SOFTWARE") RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE
+* PROVIDED TO BUYER ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY
+* DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+* LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+* PARTICULAR PURPOSE OR NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE
+* ANY WARRANTY WHATSOEVER WITH RESPECT TO THE SOFTWARE OF ANY THIRD PARTY
+* WHICH MAY BE USED BY, INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK
+* SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY
+* WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE
+* FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S SPECIFICATION OR TO
+* CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL
+* BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT
+* ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY
+* BUYER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT
+* OF LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING
+* THEREOF AND RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN
+* FRANCISCO, CA, UNDER THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE
+* (ICC).
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                         C O M P I L E R   F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                                 M A C R O S
+********************************************************************************
+*/
+#define CMB_STUB_LOG_INFO(fmt, arg...) printk(KERN_INFO fmt, ##arg)
+#define CMB_STUB_LOG_WARN(fmt, arg...) printk(KERN_WARNING fmt, ##arg)
+#define CMB_STUB_LOG_DBG(fmt, arg...) printk(KERN_DEBUG fmt, ##arg)
+
+
+/*******************************************************************************
+*                    E X T E R N A L   R E F E R E N C E S
+********************************************************************************
+*/
+#include <linux/kernel.h>
+#include <linux/module.h>
+//#include <cust_gpio_usage.h>
+//#include <mach/mt6573_pll.h> /* clr_device_working_ability, MT65XX_PDN_PERI_UART3, DEEP_IDLE_STATE, MT65XX_PDN_PERI_MSDC2 */
+//#include <mach/mt6575_dcm.h>
+// TODO: [FixMe][GeorgeKuo] keep prototype unchanged temporarily. Replace it
+// when integrate MT6628 & ALPS & other built-in modules, such as AUDIO.
+//#include <mach/mt_combo.h>
+
+#include <mach/mtk_wcn_cmb_stub.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 wmt_aif_ctrl_cb cmb_stub_aif_ctrl_cb = NULL;
+static wmt_func_ctrl_cb cmb_stub_func_ctrl_cb = NULL;
+static CMB_STUB_AIF_X cmb_stub_aif_stat = CMB_STUB_AIF_0;
+
+/* 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]
+ */
+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,
+};
+
+/*******************************************************************************
+*                  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 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;
+
+    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_LOG_INFO("[cmb_stub] unregistered \n"); /* KERN_DEBUG */
+
+    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;
+        return ret;
+    }
+    else {
+        CMB_STUB_LOG_WARN("[cmb_stub] aif_ctrl_cb null \n");
+        return -2;
+    }
+}
+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]
+ */
+int
+mt_combo_audio_ctrl_ex (COMBO_AUDIO_STATE state, u32 clt_ctrl)
+{
+    /* input sanity check */
+    if (COMBO_AUDIO_STATE_MAX < state) {
+        CMB_STUB_LOG_WARN("[cmb_stub] invalid COMBO_AUDIO_STATE(%d)\n", state);
+        return -1;
+    }
+
+    return mtk_wcn_cmb_stub_aif_ctrl(audio2aif[state],
+        (clt_ctrl) ? CMB_STUB_AIF_CTRL_EN : CMB_STUB_AIF_CTRL_DIS );
+}
+EXPORT_SYMBOL(mt_combo_audio_ctrl_ex);
+
+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);
+
+/*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;
+
+    const char *combo_if_name[] =
+    {   "COMBO_IF_UART",
+        "COMBO_IF_MSDC"
+    };
+
+    if(src != COMBO_IF_UART && src!= COMBO_IF_MSDC){
+        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);
+    }
+
+    /*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);
+            } else {
+                //set_device_working_ability(MT65XX_PDN_PERI_UART3, DEEP_IDLE_STATE);
+                //enable_dpidle_by_bit(MT65XX_PDN_PERI_UART2);
+            }
+            ret = 0;
+            break;
+
+        case COMBO_IF_MSDC:
+            if(enter == 0){
+                //clr_device_working_ability(MT65XX_PDN_PERI_MSDC2, DEEP_IDLE_STATE);
+            } else {
+                //set_device_working_ability(MT65XX_PDN_PERI_MSDC2, DEEP_IDLE_STATE);
+            }
+            ret = 0;
+            break;
+
+        default:
+            ret = -1;
+            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);
+
diff --git a/drivers/mtk_wcn_combo/common/platform/rockchip/wmt_plat_rockchip.c b/drivers/mtk_wcn_combo/common/platform/rockchip/wmt_plat_rockchip.c
new file mode 100755 (executable)
index 0000000..d90b319
--- /dev/null
@@ -0,0 +1,1012 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ *
+ * MediaTek Inc. (C) 2010. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+
+
+/*! \file
+    \brief  Declaration of library functions
+
+    Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+/*******************************************************************************
+* Copyright (c) 2009 MediaTek Inc.
+*
+* All rights reserved. Copying, compilation, modification, distribution
+* or any other use whatsoever of this material is strictly prohibited
+* except in accordance with a Software License Agreement with
+* MediaTek Inc.
+********************************************************************************
+*/
+
+/*******************************************************************************
+* LEGAL DISCLAIMER
+*
+* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND
+* AGREES THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK
+* SOFTWARE") RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE
+* PROVIDED TO BUYER ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY
+* DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+* LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+* PARTICULAR PURPOSE OR NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE
+* ANY WARRANTY WHATSOEVER WITH RESPECT TO THE SOFTWARE OF ANY THIRD PARTY
+* WHICH MAY BE USED BY, INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK
+* SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY
+* WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE
+* FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S SPECIFICATION OR TO
+* CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL
+* BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT
+* ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY
+* BUYER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT
+* OF LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING
+* THEREOF AND RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN
+* FRANCISCO, CA, UNDER THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE
+* (ICC).
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+*                         C O M P I L E R   F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                                 M A C R O S
+********************************************************************************
+*/
+#include <asm/mach-types.h>
+#include <linux/delay.h>
+#include <mach/gpio.h>
+#include <mach/io.h>
+#include <linux/platform_device.h>
+
+#if CONFIG_HAS_WAKELOCK
+#include <linux/wakelock.h>
+#define CFG_WMT_WAKELOCK_SUPPORT 1
+#endif
+
+
+#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
+********************************************************************************
+*/
+
+/*header files*/
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/spinlock.h>
+
+/* MTK_WCN_COMBO header files */
+#include "wmt_plat.h"
+#include "wmt_exp.h"
+#include "mtk_wcn_cmb_hw.h"
+
+/*******************************************************************************
+*                              C O N S T A N T S
+********************************************************************************
+*/
+
+
+#define GPIO_MT6620_PMUEN              XXX
+#define GPIO_MT6620_SYSRST             XXX
+#define GPIO_MT6620_LDO_EN     XXX
+#define INT_6620              XXX
+
+/*******************************************************************************
+*                             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_func_ctrl (UINT32 type, UINT32 on);
+static VOID wmt_plat_bgf_eirq_cb (VOID);
+
+static INT32 wmt_plat_ldo_ctrl (ENUM_PIN_STATE state);
+static INT32 wmt_plat_pmu_ctrl (ENUM_PIN_STATE state);
+static INT32 wmt_plat_rtc_ctrl (ENUM_PIN_STATE state);
+static INT32 wmt_plat_rst_ctrl (ENUM_PIN_STATE state);
+static INT32 wmt_plat_bgf_eint_ctrl (ENUM_PIN_STATE state);
+static INT32 wmt_plat_wifi_eint_ctrl (ENUM_PIN_STATE state);
+static INT32 wmt_plat_all_eint_ctrl (ENUM_PIN_STATE state);
+static INT32 wmt_plat_uart_ctrl (ENUM_PIN_STATE state);
+static INT32 wmt_plat_pcm_ctrl (ENUM_PIN_STATE state);
+static INT32 wmt_plat_i2s_ctrl (ENUM_PIN_STATE state);
+static INT32 wmt_plat_sdio_pin_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 gWmtDbgLvl = WMT_LOG_INFO;
+
+unsigned int g_balance_flag;
+spinlock_t g_balance_lock;
+unsigned int g_bgf_irq = 69;//INT_6620;//bgf eint number
+/*******************************************************************************
+*                           P R I V A T E   D A T A
+********************************************************************************
+*/
+
+
+
+
+#if CFG_WMT_WAKELOCK_SUPPORT
+static OSAL_SLEEPABLE_LOCK gOsSLock;
+static struct wake_lock wmtWakeLock;
+#endif
+
+irq_cb wmt_plat_bgf_irq_cb = NULL;
+device_audio_if_cb wmt_plat_audio_if_cb = NULL;
+const static fp_set_pin gfp_set_pin_table[] =
+{
+    [PIN_LDO] = wmt_plat_ldo_ctrl,
+    [PIN_PMU] = wmt_plat_pmu_ctrl,
+    [PIN_RTC] = wmt_plat_rtc_ctrl,
+    [PIN_RST] = wmt_plat_rst_ctrl,
+    [PIN_BGF_EINT] = wmt_plat_bgf_eint_ctrl,
+    [PIN_WIFI_EINT] = wmt_plat_wifi_eint_ctrl,
+    [PIN_ALL_EINT] = wmt_plat_all_eint_ctrl,
+    [PIN_UART_GRP] = wmt_plat_uart_ctrl,
+    [PIN_PCM_GRP] = wmt_plat_pcm_ctrl,
+    [PIN_I2S_GRP] = wmt_plat_i2s_ctrl,
+    [PIN_SDIO_GRP] = wmt_plat_sdio_pin_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;
+
+    /* input sanity check */
+    if ( (CMB_STUB_AIF_MAX <= state)
+        || (CMB_STUB_AIF_CTRL_MAX <= ctrl) ) {
+        iRet = -1;
+        WMT_ERR_FUNC("WMT-PLAT: invalid para, state(%d), ctrl(%d),iRet(%d) \n", state, ctrl, iRet);
+        return iRet;
+    }
+    if (0/*I2S/PCM share pin*/) {
+        // TODO: [FixMe][GeorgeKuo] how about MT6575? The following is applied to MT6573E1 only!!
+        pinShare = 1;
+        WMT_INFO_FUNC( "PCM/I2S pin share\n");
+    }
+    else{ //E1 later
+        pinShare = 0;
+        WMT_INFO_FUNC( "PCM/I2S pin seperate\n");
+    }
+
+    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_PCM_GRP, PIN_STA_DEINIT);
+        iRet += wmt_plat_gpio_ctrl(PIN_I2S_GRP, PIN_STA_DEINIT);
+        break;
+
+    case CMB_STUB_AIF_1:
+        iRet += wmt_plat_gpio_ctrl(PIN_PCM_GRP, PIN_STA_INIT);
+        iRet += wmt_plat_gpio_ctrl(PIN_I2S_GRP, PIN_STA_DEINIT);
+        break;
+
+    case CMB_STUB_AIF_2:
+        iRet += wmt_plat_gpio_ctrl(PIN_PCM_GRP, PIN_STA_DEINIT);
+        iRet += wmt_plat_gpio_ctrl(PIN_I2S_GRP, PIN_STA_INIT);
+        break;
+
+    case CMB_STUB_AIF_3:
+        iRet += wmt_plat_gpio_ctrl(PIN_PCM_GRP, PIN_STA_INIT);
+        iRet += wmt_plat_gpio_ctrl(PIN_I2S_GRP, PIN_STA_INIT);
+        break;
+
+    default:
+        /* FIXME: move to cust folder? */
+        WMT_ERR_FUNC("invalid state [%d]\n", state);
+        return -1;
+        break;
+    }
+
+    if (CMB_STUB_AIF_CTRL_EN == ctrl) {
+        WMT_INFO_FUNC("call chip aif setting \n");
+        /* need to control chip side GPIO */
+        //iRet += wmt_lib_set_aif(state, (pinShare) ? MTK_WCN_BOOL_TRUE : MTK_WCN_BOOL_FALSE);
+               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_WARN_FUNC("wmt_plat_audio_if_cb is not registered \n");
+                   iRet -= 1;
+               }
+    }
+    else {
+        WMT_INFO_FUNC("skip chip aif setting \n");
+    }
+    return iRet;
+
+}
+
+#if CFG_WMT_PS_SUPPORT
+irqreturn_t irq_handler(int i, void *arg)
+{
+    wmt_plat_bgf_eirq_cb();
+    return IRQ_HANDLED;
+}
+#endif
+
+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_WARN_FUNC("WMT-PLAT: wmt_plat_bgf_irq_cb not registered\n");
+               }
+#else
+               return;
+#endif
+}
+
+
+
+VOID wmt_lib_plat_irq_cb_reg (irq_cb bgf_irq_cb)
+{
+    wmt_plat_bgf_irq_cb = bgf_irq_cb;
+}
+
+VOID wmt_lib_plat_aif_cb_reg (device_audio_if_cb aif_ctrl_cb)
+{
+    wmt_plat_audio_if_cb = aif_ctrl_cb;
+}
+
+
+
+
+
+
+INT32
+wmt_plat_init (P_PWR_SEQ_TIME pPwrSeqTime)
+{
+    //CMB_STUB_CB stub_cb;
+    /*PWR_SEQ_TIME pwr_seq_time;*/
+    INT32 iret;
+
+    //stub_cb.aif_ctrl_cb = wmt_plat_audio_ctrl;
+    //stub_cb.func_ctrl_cb = wmt_plat_func_ctrl;
+    //stub_cb.size = sizeof(stub_cb);
+
+    /* register to cmb_stub */
+    //iret = mtk_wcn_cmb_stub_reg(&stub_cb);
+
+    /* init cmb_hw */
+    iret += mtk_wcn_cmb_hw_init(pPwrSeqTime);
+
+    /*init wmt function ctrl wakelock if wake lock is supported by host platform*/
+    #ifdef CFG_WMT_WAKELOCK_SUPPORT
+    wake_lock_init(&wmtWakeLock, WAKE_LOCK_SUSPEND, "wmtFuncCtrl");
+    osal_sleepable_lock_init(&gOsSLock);
+    #endif
+
+    spin_lock_init(&g_balance_lock);
+
+    WMT_DBG_FUNC("WMT-PLAT: ALPS platform init (%d)\n", iret);
+
+    return 0;
+}
+
+
+INT32
+wmt_plat_deinit (VOID)
+{
+    INT32 iret;
+
+    /* 1. de-init cmb_hw */
+    iret = mtk_wcn_cmb_hw_deinit();
+    /* 2. unreg to cmb_stub */
+    iret += mtk_wcn_cmb_stub_unreg();
+    /*3. wmt wakelock deinit*/
+    #ifdef CFG_WMT_WAKELOCK_SUPPORT
+    wake_lock_destroy(&wmtWakeLock);
+    osal_sleepable_lock_deinit(&gOsSLock);
+    WMT_DBG_FUNC("destroy wmtWakeLock\n");
+    #endif
+    WMT_DBG_FUNC("WMT-PLAT: ALPS platform init (%d)\n", iret);
+
+    return 0;
+}
+
+INT32 wmt_plat_sdio_ctrl (WMT_SDIO_SLOT_NUM sdioPortType, ENUM_FUNC_STATE on)
+{
+    if (FUNC_OFF == on)  {
+        /* add control logic here to generate SDIO CARD REMOVAL event to mmc/sd
+         * controller. SDIO card removal operation and remove success messages
+         * are expected.
+         */
+    }
+    else {
+        /* add control logic here to generate SDIO CARD INSERTION event to mmc/sd
+         * controller. SDIO card detection operation and detect success messages
+         * are expected.
+         */
+    }
+    return 0;
+}
+
+#if 0
+INT32
+wmt_plat_irq_ctrl (
+    ENUM_FUNC_STATE state
+    )
+{
+    return -1;
+}
+#endif
+
+static INT32
+wmt_plat_dump_pin_conf (VOID)
+{
+    WMT_INFO_FUNC( "[WMT-PLAT]=>dump wmt pin configuration start<=\n");
+    WMT_INFO_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_cmb_hw_pwr_on();
+        break;
+
+    case FUNC_OFF:
+        ret = mtk_wcn_cmb_hw_pwr_off();
+        break;
+
+    case FUNC_RST:
+        ret = mtk_wcn_cmb_hw_rst();
+        break;
+
+    default:
+        WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) in pwr_ctrl\n", state);
+        break;
+    }
+
+    return ret;
+}
+
+INT32 wmt_plat_ps_ctrl (ENUM_FUNC_STATE state)
+{
+    return -1;
+}
+
+INT32
+wmt_plat_eirq_ctrl (
+    ENUM_PIN_ID id,
+    ENUM_PIN_STATE state
+    )
+{
+    INT32 iRet;
+    unsigned int flags;
+    // 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 ) ) {
+        iRet = -1;
+        WMT_WARN_FUNC("WMT-PLAT:invalid PIN_STATE(%d) in eirq_ctrl for PIN(%d), ret(%d) \n", state, id, iRet);
+        return iRet;
+    }
+
+    iRet = -2;
+    switch (id) {
+    case PIN_BGF_EINT:
+        if (PIN_STA_INIT == state) {
+            /*request irq,low level triggered*/
+       //iRet = request_irq(INT_6620, irq_handler,  IRQF_TRIGGER_LOW | IRQF_DISABLED, "MTK6620_BT", NULL);
+               
+           
+           g_balance_flag = 1;//do not modify this value
+            WMT_INFO_FUNC("WMT-PLAT:BGFInt (init) \n");
+        }
+        else if (PIN_STA_EINT_EN == state) {
+            /*enable irq*/
+           spin_lock_irqsave(&g_balance_lock,flags);
+           if(g_balance_flag)
+           {
+               /*if enter this case, the bgf eint has been enabled,so skip it.*/
+               WMT_INFO_FUNC("BGF_EINT has been enabled,g_balance_flag(%d)!\n",g_balance_flag);
+           }
+           else
+           {
+               /*do real irq enable implement is this case*/
+                   //enable_irq(INT_6620);
+               g_balance_flag++;
+                WMT_INFO_FUNC("WMT-PLAT:BGFInt (en),g_balance_flag(%d)\n",g_balance_flag);
+           }
+           spin_unlock_irqrestore(&g_balance_lock,flags);
+        }
+        else if (PIN_STA_EINT_DIS == state) {
+            /*disable irq*/
+           spin_lock_irqsave(&g_balance_lock,flags);
+           if(!g_balance_flag)
+           {
+               /*if enter this case, the bgf eint has been disabled,so skip it.*/
+               WMT_INFO_FUNC("BGF_EINT has been disabled,g_balance_flag(%d)!\n",g_balance_flag);
+            }
+           else
+           {
+               /*do real irq disable implement is this case*/
+                   //disable_irq_nosync(INT_6620);
+               g_balance_flag--;
+                WMT_INFO_FUNC("WMT-PLAT:BGFInt (dis) g_balance_flag(%d)\n",g_balance_flag);
+           }
+           spin_unlock_irqrestore(&g_balance_lock,flags);
+        }
+        else {
+            /* de-init: free irq*/
+            //free_irq(INT_6620,NULL);
+            WMT_INFO_FUNC("WMT-PLAT:BGFInt (deinit) \n");
+
+        }
+        iRet = 0;
+        break;
+
+    case PIN_ALL_EINT:
+#if 0
+        if (PIN_STA_INIT == state) {
+
+            WMT_DBG_FUNC("WMT-PLAT:ALLInt (INIT but not used yet) \n");
+        }
+        else if (PIN_STA_EINT_EN == state) {
+             WMT_DBG_FUNC("WMT-PLAT:ALLInt (EN but not used yet) \n");
+        }
+        else if (PIN_STA_EINT_DIS == state) {
+            WMT_DBG_FUNC("WMT-PLAT:ALLInt (DIS but not used yet) \n");
+        }
+        else {
+
+            WMT_DBG_FUNC("WMT-PLAT:ALLInt (DEINIT but not used yet) \n");
+            /* de-init: nothing to do in ALPS, such as un-registration... */
+        }
+#else
+        WMT_DBG_FUNC("WMT-PLAT:ALLInt (not used yet) \n");
+#endif
+        iRet = 0;
+        break;
+
+    default:
+        WMT_WARN_FUNC("WMT-PLAT:unsupported EIRQ(PIN_ID:%d) in eirq_ctrl, ret (%d)\n", id, iRet);
+        iRet = -1;
+        break;
+    }
+
+    return iRet;
+
+}
+
+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 */
+        }
+        else {
+            WMT_WARN_FUNC("WMT-PLAT: null fp for gpio_ctrl(%d)\n", id);
+            return -2;
+        }
+    }
+       WMT_ERR_FUNC("WMT-PLAT:[out of range] id(%d), state (%d)\n", id, state);
+    return -1;
+}
+
+INT32
+wmt_plat_ldo_ctrl (
+    ENUM_PIN_STATE state
+    )
+{
+    switch(state)
+    {
+    case PIN_STA_INIT:
+        /*set to gpio output low, disable pull*/
+        WMT_DBG_FUNC("WMT-PLAT:LDO init (out 0) \n");
+        break;
+
+    case PIN_STA_OUT_H:
+        WMT_DBG_FUNC("WMT-PLAT:LDO (out 1) \n");
+        break;
+
+    case PIN_STA_OUT_L:
+        WMT_DBG_FUNC("WMT-PLAT:LDO (out 0) \n");
+        break;
+
+    case PIN_STA_IN_L:
+    case PIN_STA_DEINIT:
+        /*set to gpio input low, pull down enable*/
+        WMT_DBG_FUNC("WMT-PLAT:LDO deinit (in pd) \n");
+        break;
+
+    default:
+        WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on LDO\n", state);
+        break;
+    }
+    return 0;
+}
+
+INT32
+wmt_plat_pmu_ctrl (
+    ENUM_PIN_STATE state
+    )
+{
+    switch(state)
+    {
+    case PIN_STA_INIT:
+        /*set to gpio output low, disable pull*/
+       
+       printk("WMT-PLAT:PMU init (out 0) \n");
+        break;
+
+    case PIN_STA_OUT_H:
+       
+        printk("WMT-PLAT:PMU (out 1) \n");
+        break;
+
+    case PIN_STA_OUT_L:
+       
+        printk("WMT-PLAT:PMU (out 0) \n");
+        break;
+
+    case PIN_STA_IN_L:
+    case PIN_STA_DEINIT:
+        /*set to gpio input low, pull down enable*/
+       
+        printk("WMT-PLAT:PMU deinit (in pd) \n");
+        break;
+
+    default:
+        printk("WMT-PLAT:Warnning, invalid state(%d) on PMU\n", state);
+        break;
+    }
+
+    return 0;
+}
+
+INT32
+wmt_plat_rtc_ctrl (
+    ENUM_PIN_STATE state
+    )
+{
+    switch(state)
+    {
+    case PIN_STA_INIT:
+        WMT_DBG_FUNC("WMT-PLAT:RTC init \n");
+        break;
+
+    default:
+        WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on RTC\n", state);
+        break;
+    }
+    return 0;
+}
+
+
+INT32
+wmt_plat_rst_ctrl (
+    ENUM_PIN_STATE state
+    )
+{
+    switch(state)
+    {
+        case PIN_STA_INIT:
+            /*set to gpio output low, disable pull*/
+
+            printk("WMT-PLAT:RST init (out 0) \n");
+            break;
+
+        case PIN_STA_OUT_H:
+
+            printk("WMT-PLAT:RST (out 1) \n");
+            break;
+
+        case PIN_STA_OUT_L:
+
+            printk("WMT-PLAT:RST (out 0) \n");
+            break;
+
+        case PIN_STA_IN_L:
+        case PIN_STA_DEINIT:
+            /*set to gpio input low, pull down enable*/
+
+            printk("WMT-PLAT:RST deinit (in pd) \n");
+            break;
+
+        default:
+            printk("WMT-PLAT:Warnning, invalid state(%d) on RST\n", state);
+            break;
+    }
+
+    return 0;
+}
+
+INT32
+wmt_plat_bgf_eint_ctrl (
+    ENUM_PIN_STATE state
+    )
+{
+
+    switch(state)
+    {
+        case PIN_STA_INIT:
+            /*set to gpio input low, pull down eanble*/
+
+            WMT_DBG_FUNC("WMT-PLAT:BGFInt init(in pd) \n");
+            break;
+
+        case PIN_STA_MUX:
+            /* first: set to EINT mode,interrupt input, pull up enable*/
+
+            WMT_DBG_FUNC("WMT-PLAT:BGFInt mux (eint) \n");
+
+           /* second: enable bgf irq wake up host function*/
+            do {
+                int iret;
+                //iret = enable_irq_wake(g_bgf_irq);//enable bgf irq wake up host function
+                //WMT_INFO_FUNC("enable_irq_wake(bgf:%d)++, ret(%d)\n", g_bgf_irq, iret);
+            } while (0);
+            break;
+
+        case PIN_STA_IN_L:
+        case PIN_STA_DEINIT:
+           /* first: disable bgf irq wake up host function*/
+            do {
+                int iret;
+                //iret = disable_irq_wake(g_bgf_irq);//disable bgf irq wake up host function
+                if (iret) {
+                    //WMT_WARN_FUNC("disable_irq_wake(bgf:%d) fail(%d)\n", g_bgf_irq, iret);
+                    iret = 0;
+                }
+                else {
+                    //WMT_INFO_FUNC("disable_irq_wake(bgf:%d)--, ret(%d)\n", g_bgf_irq, iret);
+                }
+            } while (0);
+
+           /* second: set to gpio input low, pull down enable*/
+            WMT_DBG_FUNC("WMT-PLAT:BGFInt deinit(in pd) \n");
+            break;
+
+        default:
+            WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on BGF EINT\n", state);
+            break;
+    }
+
+    return 0;
+}
+
+
+INT32 wmt_plat_wifi_eint_ctrl(ENUM_PIN_STATE state)
+{
+#if 0
+    switch(state)
+    {
+        case PIN_STA_INIT:
+            break;
+        case PIN_STA_MUX:
+
+            break;
+        case PIN_STA_EINT_EN:
+            break;
+        case PIN_STA_EINT_DIS:
+            break;
+        case PIN_STA_IN_L:
+        case PIN_STA_DEINIT:
+            /*set to gpio input low, pull down enable*/
+            break;
+        default:
+            WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on WIFI EINT\n", state);
+            break;
+    }
+#else
+    WMT_INFO_FUNC("WMT-PLAT:WIFI EINT is controlled by MSDC driver \n");
+#endif
+    return 0;
+}
+
+
+INT32
+wmt_plat_all_eint_ctrl (
+    ENUM_PIN_STATE state
+    )
+{
+    switch(state)
+    {
+        case PIN_STA_INIT:
+                 /*set to gpio input low, pull down eanble*/
+            WMT_DBG_FUNC("WMT-PLAT:ALLInt init(in pd) \n");
+            break;
+
+        case PIN_STA_MUX:
+                 /*set to gpio EINT mode, pull down enable*/
+            break;
+
+        case PIN_STA_IN_L:
+        case PIN_STA_DEINIT:
+            /*set to gpio input low, pull down enable*/
+            break;
+
+        default:
+            WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on ALL EINT\n", state);
+            break;
+    }
+    return 0;
+}
+
+INT32 wmt_plat_uart_ctrl(ENUM_PIN_STATE state)
+{
+    switch(state)
+    {
+    case PIN_STA_MUX:
+    case PIN_STA_INIT:
+        WMT_DBG_FUNC("WMT-PLAT:UART init (mode_01, uart) \n");
+        break;
+    case PIN_STA_IN_L:
+    case PIN_STA_DEINIT:
+        WMT_DBG_FUNC("WMT-PLAT:UART deinit (out 0) \n");
+        break;
+
+    default:
+        WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on UART Group\n", state);
+        break;
+    }
+
+    return 0;
+}
+
+
+INT32 wmt_plat_pcm_ctrl(ENUM_PIN_STATE state)
+{
+    switch(state)
+    {
+    case PIN_STA_MUX:
+    case PIN_STA_INIT:
+         /*set to PCM function*/
+        WMT_DBG_FUNC("WMT-PLAT:PCM init (pcm) \n");
+        break;
+
+    case PIN_STA_IN_L:
+    case PIN_STA_DEINIT:
+        WMT_DBG_FUNC("WMT-PLAT:PCM deinit (out 0) \n");
+        break;
+
+    default:
+        WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on PCM Group\n", state);
+        break;
+    }
+    return 0;
+}
+
+
+INT32 wmt_plat_i2s_ctrl(ENUM_PIN_STATE state)
+{
+#ifndef FM_ANALOG_INPUT
+    switch(state)
+    {
+    case PIN_STA_INIT:
+    case PIN_STA_MUX:
+    /*set to I2S function*/
+        WMT_DBG_FUNC("WMT-PLAT:I2S init \n");
+        break;
+    case PIN_STA_IN_L:
+    case PIN_STA_DEINIT:
+    /*set to gpio input low, pull down enable*/
+        WMT_DBG_FUNC("WMT-PLAT:I2S deinit (out 0) \n");
+        break;
+    default:
+        WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on I2S Group\n", state);
+        break;
+    }
+#else
+        WMT_INFO_FUNC( "[MT6620]warnning:FM analog mode is set, no I2S GPIO settings should be modified by combo driver\n");
+#endif
+
+    return 0;
+}
+
+INT32
+wmt_plat_sdio_pin_ctrl (
+    ENUM_PIN_STATE state
+    )
+{
+    switch (state) {
+    case PIN_STA_INIT:
+    case PIN_STA_MUX:
+        break;
+    case PIN_STA_DEINIT:
+        break;
+    default:
+        WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on SDIO Group\n", state);
+        break;
+    }
+    return 0;
+}
+
+static INT32
+wmt_plat_gps_sync_ctrl (
+    ENUM_PIN_STATE state
+    )
+{
+    switch (state) {
+    case PIN_STA_INIT:
+    case PIN_STA_DEINIT:
+    /*set GPS_SYNC GPIO to GPIO mode, pull disable,output low*/
+        break;
+
+    case PIN_STA_MUX:
+    /*set GPS_SYNC GPIO to GPS_SYNC function*/
+        break;
+
+    default:
+        break;
+    }
+    return 0;
+}
+
+
+static INT32
+wmt_plat_gps_lna_ctrl (
+        ENUM_PIN_STATE state
+        )
+{
+    switch (state) {
+    case PIN_STA_INIT:
+    case PIN_STA_DEINIT:
+    /*set GPS_LNA GPIO to GPIO mode, pull disable,output low*/
+        break;
+    case PIN_STA_OUT_H:
+    /*set GPS_LNA GPIO to GPIO mode, pull disable,output high*/
+        break;
+    case PIN_STA_OUT_L:
+    /*set GPS_LNA GPIO to GPIO mode, pull disable,output low*/
+        break;
+
+    default:
+        WMT_WARN_FUNC("%d mode not defined for  gps lna pin !!!\n", state);
+        break;
+    }
+    return 0;
+
+}
+
+
+
+INT32 wmt_plat_wake_lock_ctrl(ENUM_WL_OP opId)
+{
+#ifdef CFG_WMT_WAKELOCK_SUPPORT
+    static INT32 counter = 0;
+
+
+    osal_lock_sleepable_lock( &gOsSLock);
+    if (WL_OP_GET == opId)
+    {
+        ++counter;
+    }else if (WL_OP_PUT == opId)
+    {
+        --counter;
+    }
+    osal_unlock_sleepable_lock( &gOsSLock);
+    if (WL_OP_GET == opId && counter == 1)
+    {
+        wake_lock(&wmtWakeLock);
+        WMT_DBG_FUNC("WMT-PLAT: after wake_lock(%d), counter(%d)\n", wake_lock_active(&wmtWakeLock), counter);
+
+    }
+    else if (WL_OP_PUT == opId && counter == 0)
+    {
+        wake_unlock(&wmtWakeLock);
+        WMT_DBG_FUNC("WMT-PLAT: after wake_unlock(%d), counter(%d)\n", wake_lock_active(&wmtWakeLock), counter);
+    }
+    else
+    {
+        WMT_WARN_FUNC("WMT-PLAT: wakelock status(%d), counter(%d)\n", wake_lock_active(&wmtWakeLock), counter);
+    }
+    return 0;
+#else
+    WMT_WARN_FUNC("WMT-PLAT: host awake function is not supported.");
+    return 0;
+
+#endif
+}
+
diff --git a/drivers/mtk_wcn_combo/common/platform/rockchip/wmt_plat_stub.c b/drivers/mtk_wcn_combo/common/platform/rockchip/wmt_plat_stub.c
new file mode 100755 (executable)
index 0000000..bcb1380
--- /dev/null
@@ -0,0 +1,110 @@
+/*! \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
+********************************************************************************
+*/
+
+
+#if CONFIG_HAS_WAKELOCK
+#include <linux/wakelock.h>
+#define CFG_WMT_WAKELOCK_SUPPORT 1
+#endif
+
+#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
+********************************************************************************
+*/
+
+/* ALPS and COMBO header files */
+#include <mach/mtk_wcn_cmb_stub.h>
+
+/* MTK_WCN_COMBO header files */
+#include "wmt_plat.h"
+#include "wmt_plat_stub.h"
+#include "wmt_exp.h"
+#include <mach/mtk_wcn_cmb_stub.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
+********************************************************************************
+*/
+
+static VOID wmt_plat_func_ctrl (UINT32 type, UINT32 on);
+
+
+
+/*******************************************************************************
+*                            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 S
+********************************************************************************
+*/
+
+static VOID wmt_plat_func_ctrl (UINT32 type, UINT32 on)
+{
+    if (on) {
+        mtk_wcn_wmt_func_on((ENUM_WMTDRV_TYPE_T)type);
+    }
+    else {
+        mtk_wcn_wmt_func_off((ENUM_WMTDRV_TYPE_T)type);
+    }
+    return;
+}
+
+
+INT32 wmt_plat_stub_init (void)
+{
+    INT32 iRet = -1;
+    CMB_STUB_CB stub_cb;
+    stub_cb.aif_ctrl_cb = wmt_plat_audio_ctrl;
+    stub_cb.func_ctrl_cb = wmt_plat_func_ctrl;
+    stub_cb.size = sizeof(stub_cb);
+
+    /* register to cmb_stub */
+    iRet = mtk_wcn_cmb_stub_reg(&stub_cb);
+    return iRet;
+}
+
+
diff --git a/drivers/mtk_wcn_combo/common/platform/sample/mtk_wcn_cmb_hw.c b/drivers/mtk_wcn_combo/common/platform/sample/mtk_wcn_cmb_hw.c
new file mode 100755 (executable)
index 0000000..980ef58
--- /dev/null
@@ -0,0 +1,346 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ *
+ * MediaTek Inc. (C) 2010. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+
+
+/*! \file
+    \brief  Declaration of library functions
+
+    Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+/*******************************************************************************
+* Copyright (c) 2009 MediaTek Inc.
+*
+* All rights reserved. Copying, compilation, modification, distribution
+* or any other use whatsoever of this material is strictly prohibited
+* except in accordance with a Software License Agreement with
+* MediaTek Inc.
+********************************************************************************
+*/
+
+/*******************************************************************************
+* LEGAL DISCLAIMER
+*
+* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND
+* AGREES THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK
+* SOFTWARE") RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE
+* PROVIDED TO BUYER ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY
+* DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+* LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+* PARTICULAR PURPOSE OR NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE
+* ANY WARRANTY WHATSOEVER WITH RESPECT TO THE SOFTWARE OF ANY THIRD PARTY
+* WHICH MAY BE USED BY, INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK
+* SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY
+* WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE
+* FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S SPECIFICATION OR TO
+* CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL
+* BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT
+* ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY
+* BUYER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT
+* OF LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING
+* THEREOF AND RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN
+* FRANCISCO, CA, UNDER THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE
+* (ICC).
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+*                         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-CMB-HW]"
+
+
+/*******************************************************************************
+*                    E X T E R N A L   R E F E R E N C E S
+********************************************************************************
+*/
+#include "osal.h"
+#include "mtk_wcn_cmb_hw.h"
+#include "wmt_plat.h"
+#include "wmt_exp.h"
+
+/*******************************************************************************
+*                              C O N S T A N T S
+********************************************************************************
+*/
+#define DFT_RTC_STABLE_TIME 100
+#define DFT_LDO_STABLE_TIME 100
+#define DFT_RST_STABLE_TIME 30
+#define DFT_OFF_STABLE_TIME 10
+#define DFT_ON_STABLE_TIME 30
+
+/*******************************************************************************
+*                             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
+********************************************************************************
+*/
+
+PWR_SEQ_TIME gPwrSeqTime;
+
+
+
+
+/*******************************************************************************
+*                  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_cmb_hw_pwr_off (VOID)
+{
+    INT32 iRet = 0;
+    WMT_INFO_FUNC("CMB-HW, hw_pwr_off start\n");
+
+    /*1. disable irq --> should be done when do wmt-ic swDeinit period*/
+    // TODO:[FixMe][GeorgeKuo] clarify this
+
+    /*2. set bgf eint/all eint to deinit state, namely input low state*/
+    iRet += wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_DEINIT);
+    iRet += wmt_plat_gpio_ctrl(PIN_BGF_EINT, PIN_STA_DEINIT);
+    WMT_INFO_FUNC("CMB-HW, BGF_EINT IRQ unregistered and set BGF_EINT GPIO to correct state!\n");
+    /* 2.1 set ALL_EINT pin to correct state even it is not used currently */
+    iRet += wmt_plat_eirq_ctrl(PIN_ALL_EINT, PIN_STA_EINT_DIS);
+    WMT_INFO_FUNC("CMB-HW, ALL_EINT IRQ unregistered and disabled\n");
+    iRet += wmt_plat_gpio_ctrl(PIN_ALL_EINT, PIN_STA_DEINIT);
+    /* 2.2 deinit gps sync */
+    iRet += wmt_plat_gpio_ctrl(PIN_GPS_SYNC, PIN_STA_DEINIT);
+
+    /*3. set audio interface to CMB_STUB_AIF_0, BT PCM OFF, I2S OFF*/
+    iRet += wmt_plat_audio_ctrl(CMB_STUB_AIF_0, CMB_STUB_AIF_CTRL_DIS);
+
+    /*4. set control gpio into deinit state, namely input low state*/
+    iRet += wmt_plat_gpio_ctrl(PIN_SDIO_GRP, PIN_STA_DEINIT);
+    iRet += wmt_plat_gpio_ctrl(PIN_RST, PIN_STA_OUT_L);
+    iRet += wmt_plat_gpio_ctrl(PIN_PMU, PIN_STA_OUT_L);
+
+    /*5. set uart tx/rx into deinit state, namely input low state*/
+    iRet += wmt_plat_gpio_ctrl(PIN_UART_GRP, PIN_STA_DEINIT);
+
+    /* 6. Last, LDO output low */
+    iRet += wmt_plat_gpio_ctrl(PIN_LDO, PIN_STA_OUT_L);
+    
+    /*7. deinit gps_lna*/
+    iRet += wmt_plat_gpio_ctrl(PIN_GPS_LNA, PIN_STA_DEINIT);
+    
+    WMT_INFO_FUNC("CMB-HW, hw_pwr_off finish\n");
+    return iRet;
+}
+
+INT32
+mtk_wcn_cmb_hw_pwr_on (VOID)
+{
+    static UINT32 _pwr_first_time = 1;
+    INT32 iRet = 0;
+
+    WMT_INFO_FUNC("CMB-HW, hw_pwr_on start\n");
+#if 0 //IRQ should in inact state before power on, so this step is not needed
+    /* disable interrupt firstly */
+    iRet += wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_EINT_DIS);
+    iRet += wmt_plat_eirq_ctrl(PIN_ALL_EINT, PIN_STA_EINT_DIS);
+#endif
+    /*set all control and eint gpio to init state, namely input low mode*/
+    iRet += wmt_plat_gpio_ctrl(PIN_LDO, PIN_STA_INIT);
+    iRet += wmt_plat_gpio_ctrl(PIN_PMU, PIN_STA_INIT);
+    iRet += wmt_plat_gpio_ctrl(PIN_RST, PIN_STA_INIT);
+    iRet += wmt_plat_gpio_ctrl(PIN_SDIO_GRP, PIN_STA_INIT);
+    iRet += wmt_plat_gpio_ctrl(PIN_BGF_EINT, PIN_STA_INIT);
+    iRet += wmt_plat_gpio_ctrl(PIN_ALL_EINT, PIN_STA_INIT);
+    iRet += wmt_plat_gpio_ctrl(PIN_GPS_SYNC, PIN_STA_INIT);
+    iRet += wmt_plat_gpio_ctrl(PIN_GPS_LNA, PIN_STA_INIT);
+    // wmt_plat_gpio_ctrl(PIN_WIFI_EINT, PIN_STA_INIT); /* WIFI_EINT is controlled by SDIO host driver */
+    // TODO: [FixMe][George]:WIFI_EINT is used in common SDIO
+
+    /*1. pull high LDO to supply power to chip*/
+    iRet += wmt_plat_gpio_ctrl(PIN_LDO, PIN_STA_OUT_H);
+    osal_msleep(gPwrSeqTime.ldoStableTime);
+
+    /* 2. export RTC clock to chip*/
+    if (_pwr_first_time) {
+        /* rtc clock should be output all the time, so no need to enable output again*/
+        iRet += wmt_plat_gpio_ctrl(PIN_RTC, PIN_STA_INIT);
+        osal_msleep(gPwrSeqTime.rtcStableTime);
+        WMT_INFO_FUNC("CMB-HW, rtc clock exported\n");
+    }
+
+    /*3. set UART Tx/Rx to UART mode*/
+    iRet += wmt_plat_gpio_ctrl(PIN_UART_GRP, PIN_STA_INIT);
+
+    /*4. PMU->output low, RST->output low, sleep off stable time*/
+    iRet += wmt_plat_gpio_ctrl(PIN_PMU, PIN_STA_OUT_L);
+    iRet += wmt_plat_gpio_ctrl(PIN_RST, PIN_STA_OUT_L);
+    osal_msleep(gPwrSeqTime.offStableTime);
+
+    /*5. PMU->output high, sleep rst stable time*/
+    iRet += wmt_plat_gpio_ctrl(PIN_PMU, PIN_STA_OUT_H);
+    osal_msleep(gPwrSeqTime.rstStableTime);
+
+    /*6. RST->output high, sleep on stable time*/
+    iRet += wmt_plat_gpio_ctrl(PIN_RST, PIN_STA_OUT_H);
+    osal_msleep(gPwrSeqTime.onStableTime);
+
+    /*7. set audio interface to CMB_STUB_AIF_1, BT PCM ON, I2S OFF*/
+    /* BT PCM bus default mode. Real control is done by audio */
+    iRet += wmt_plat_audio_ctrl(CMB_STUB_AIF_1, CMB_STUB_AIF_CTRL_DIS);
+
+    /*8. set EINT< -ommited-> move this to WMT-IC module, where common sdio interface will be identified and do proper operation*/
+    // 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_INFO_FUNC("CMB-HW, BGF_EINT IRQ registered and disabled \n");
+
+    /* 8.1 set ALL_EINT pin to correct state even it is not used currently */
+    iRet += wmt_plat_gpio_ctrl(PIN_ALL_EINT, PIN_STA_MUX);
+    iRet += wmt_plat_eirq_ctrl(PIN_ALL_EINT, PIN_STA_INIT);
+    iRet += wmt_plat_eirq_ctrl(PIN_ALL_EINT, PIN_STA_EINT_DIS);
+    WMT_INFO_FUNC("CMB-HW, hw_pwr_on finish (%d)\n", iRet);
+
+    _pwr_first_time = 0;
+    return iRet;
+
+}
+
+INT32
+mtk_wcn_cmb_hw_rst (VOID)
+{
+    INT32 iRet = 0;
+    WMT_INFO_FUNC("CMB-HW, hw_rst start, eirq should be disabled before this step\n");
+
+    /*1. PMU->output low, RST->output low, sleep off stable time*/
+    iRet += wmt_plat_gpio_ctrl(PIN_PMU, PIN_STA_OUT_L);
+    iRet += wmt_plat_gpio_ctrl(PIN_RST, PIN_STA_OUT_L);
+    osal_msleep(gPwrSeqTime.offStableTime);
+
+    /*2. PMU->output high, sleep rst stable time*/
+    iRet += wmt_plat_gpio_ctrl(PIN_PMU, PIN_STA_OUT_H);
+    osal_msleep(gPwrSeqTime.rstStableTime);
+
+    /*3. RST->output high, sleep on stable time*/
+    iRet += wmt_plat_gpio_ctrl(PIN_RST, PIN_STA_OUT_H);
+    osal_msleep(gPwrSeqTime.onStableTime);
+    WMT_INFO_FUNC("CMB-HW, hw_rst finish, eirq should be enabled after this step\n");
+    return 0;
+}
+
+static VOID
+mtk_wcn_cmb_hw_dmp_seq (VOID)
+{
+    PUINT32 pTimeSlot = (PUINT32)&gPwrSeqTime;
+    WMT_INFO_FUNC("combo chip power on sequence time, RTC (%d), LDO (%d), RST(%d), OFF(%d), ON(%d)\n",
+        pTimeSlot[0], /**pTimeSlot++,*/
+        pTimeSlot[1],
+        pTimeSlot[2],
+        pTimeSlot[3],
+        pTimeSlot[4]
+        );
+    return;
+}
+
+INT32
+mtk_wcn_cmb_hw_init (
+    P_PWR_SEQ_TIME pPwrSeqTime
+    )
+{
+    if (NULL != pPwrSeqTime            && 
+        pPwrSeqTime->ldoStableTime > 0 &&
+        pPwrSeqTime->rtcStableTime > 0 &&
+        pPwrSeqTime->offStableTime > DFT_OFF_STABLE_TIME &&
+        pPwrSeqTime->onStableTime  > DFT_ON_STABLE_TIME  &&
+        pPwrSeqTime->rstStableTime > DFT_RST_STABLE_TIME
+    ) {
+        /*memcpy may be more performance*/
+        WMT_DBG_FUNC("setting hw init sequence parameters\n");
+        osal_memcpy(&gPwrSeqTime, pPwrSeqTime, osal_sizeof(gPwrSeqTime));
+    }
+    else {    
+        WMT_WARN_FUNC("invalid pPwrSeqTime parameter, use default hw init sequence parameters\n");
+        gPwrSeqTime.ldoStableTime = DFT_LDO_STABLE_TIME;
+        gPwrSeqTime.offStableTime = DFT_OFF_STABLE_TIME;
+        gPwrSeqTime.onStableTime = DFT_ON_STABLE_TIME;
+        gPwrSeqTime.rstStableTime = DFT_RST_STABLE_TIME;
+        gPwrSeqTime.rtcStableTime = DFT_RTC_STABLE_TIME;
+    }
+    mtk_wcn_cmb_hw_dmp_seq();
+    return 0;
+}
+
+INT32
+mtk_wcn_cmb_hw_deinit (VOID)
+{
+
+    WMT_WARN_FUNC("mtk_wcn_cmb_hw_deinit start, set to default hw init sequence parameters\n");
+    gPwrSeqTime.ldoStableTime = DFT_LDO_STABLE_TIME;
+    gPwrSeqTime.offStableTime = DFT_OFF_STABLE_TIME;
+    gPwrSeqTime.onStableTime = DFT_ON_STABLE_TIME;
+    gPwrSeqTime.rstStableTime = DFT_RST_STABLE_TIME;
+    gPwrSeqTime.rtcStableTime = DFT_RTC_STABLE_TIME;
+    WMT_WARN_FUNC("mtk_wcn_cmb_hw_deinit finish\n");
+    return 0;
+}
+
diff --git a/drivers/mtk_wcn_combo/common/platform/sample/mtk_wcn_cmb_stub_sample.c b/drivers/mtk_wcn_combo/common/platform/sample/mtk_wcn_cmb_stub_sample.c
new file mode 100755 (executable)
index 0000000..69546c0
--- /dev/null
@@ -0,0 +1,348 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ *
+ * MediaTek Inc. (C) 2010. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+
+
+/*! \file
+    \brief  Declaration of library functions
+
+    Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+/*******************************************************************************
+* Copyright (c) 2009 MediaTek Inc.
+*
+* All rights reserved. Copying, compilation, modification, distribution
+* or any other use whatsoever of this material is strictly prohibited
+* except in accordance with a Software License Agreement with
+* MediaTek Inc.
+********************************************************************************
+*/
+
+/*******************************************************************************
+* LEGAL DISCLAIMER
+*
+* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND
+* AGREES THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK
+* SOFTWARE") RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE
+* PROVIDED TO BUYER ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY
+* DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+* LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+* PARTICULAR PURPOSE OR NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE
+* ANY WARRANTY WHATSOEVER WITH RESPECT TO THE SOFTWARE OF ANY THIRD PARTY
+* WHICH MAY BE USED BY, INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK
+* SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY
+* WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE
+* FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S SPECIFICATION OR TO
+* CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL
+* BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT
+* ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY
+* BUYER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT
+* OF LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING
+* THEREOF AND RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN
+* FRANCISCO, CA, UNDER THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE
+* (ICC).
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                         C O M P I L E R   F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                                 M A C R O S
+********************************************************************************
+*/
+#define CMB_STUB_LOG_INFO(fmt, arg...) printk(KERN_INFO fmt, ##arg)
+#define CMB_STUB_LOG_WARN(fmt, arg...) printk(KERN_WARNING fmt, ##arg)
+#define CMB_STUB_LOG_DBG(fmt, arg...) printk(KERN_DEBUG fmt, ##arg)
+
+
+/*******************************************************************************
+*                    E X T E R N A L   R E F E R E N C E S
+********************************************************************************
+*/
+#include <linux/kernel.h>
+#include <linux/module.h>
+//#include <cust_gpio_usage.h>
+//#include <mach/mt6573_pll.h> /* clr_device_working_ability, MT65XX_PDN_PERI_UART3, DEEP_IDLE_STATE, MT65XX_PDN_PERI_MSDC2 */
+//#include <mach/mt6575_dcm.h>
+// TODO: [FixMe][GeorgeKuo] keep prototype unchanged temporarily. Replace it
+// when integrate MT6628 & ALPS & other built-in modules, such as AUDIO.
+//#include <mach/mt_combo.h>
+
+#include <mach/mtk_wcn_cmb_stub.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 wmt_aif_ctrl_cb cmb_stub_aif_ctrl_cb = NULL;
+static wmt_func_ctrl_cb cmb_stub_func_ctrl_cb = NULL;
+static CMB_STUB_AIF_X cmb_stub_aif_stat = CMB_STUB_AIF_0;
+
+/* 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]
+ */
+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,
+};
+
+/*******************************************************************************
+*                  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 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;
+
+    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_LOG_INFO("[cmb_stub] unregistered \n"); /* KERN_DEBUG */
+
+    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;
+        return ret;
+    }
+    else {
+        CMB_STUB_LOG_WARN("[cmb_stub] aif_ctrl_cb null \n");
+        return -2;
+    }
+}
+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]
+ */
+int
+mt_combo_audio_ctrl_ex (COMBO_AUDIO_STATE state, u32 clt_ctrl)
+{
+    /* input sanity check */
+    if (COMBO_AUDIO_STATE_MAX < state) {
+        CMB_STUB_LOG_WARN("[cmb_stub] invalid COMBO_AUDIO_STATE(%d)\n", state);
+        return -1;
+    }
+
+    return mtk_wcn_cmb_stub_aif_ctrl(audio2aif[state],
+        (clt_ctrl) ? CMB_STUB_AIF_CTRL_EN : CMB_STUB_AIF_CTRL_DIS );
+}
+EXPORT_SYMBOL(mt_combo_audio_ctrl_ex);
+
+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);
+
+/*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;
+
+    const char *combo_if_name[] =
+    {   "COMBO_IF_UART",
+        "COMBO_IF_MSDC"
+    };
+
+    if(src != COMBO_IF_UART && src!= COMBO_IF_MSDC){
+        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);
+    }
+
+    /*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);
+            } else {
+                //set_device_working_ability(MT65XX_PDN_PERI_UART3, DEEP_IDLE_STATE);
+                //enable_dpidle_by_bit(MT65XX_PDN_PERI_UART2);
+            }
+            ret = 0;
+            break;
+
+        case COMBO_IF_MSDC:
+            if(enter == 0){
+                //clr_device_working_ability(MT65XX_PDN_PERI_MSDC2, DEEP_IDLE_STATE);
+            } else {
+                //set_device_working_ability(MT65XX_PDN_PERI_MSDC2, DEEP_IDLE_STATE);
+            }
+            ret = 0;
+            break;
+
+        default:
+            ret = -1;
+            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);
+
diff --git a/drivers/mtk_wcn_combo/common/platform/sample/wmt_plat_sample.c b/drivers/mtk_wcn_combo/common/platform/sample/wmt_plat_sample.c
new file mode 100755 (executable)
index 0000000..73fe098
--- /dev/null
@@ -0,0 +1,1012 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ *
+ * MediaTek Inc. (C) 2010. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+
+
+/*! \file
+    \brief  Declaration of library functions
+
+    Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+/*******************************************************************************
+* Copyright (c) 2009 MediaTek Inc.
+*
+* All rights reserved. Copying, compilation, modification, distribution
+* or any other use whatsoever of this material is strictly prohibited
+* except in accordance with a Software License Agreement with
+* MediaTek Inc.
+********************************************************************************
+*/
+
+/*******************************************************************************
+* LEGAL DISCLAIMER
+*
+* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND
+* AGREES THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK
+* SOFTWARE") RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE
+* PROVIDED TO BUYER ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY
+* DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+* LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+* PARTICULAR PURPOSE OR NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE
+* ANY WARRANTY WHATSOEVER WITH RESPECT TO THE SOFTWARE OF ANY THIRD PARTY
+* WHICH MAY BE USED BY, INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK
+* SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY
+* WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE
+* FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S SPECIFICATION OR TO
+* CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL
+* BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT
+* ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY
+* BUYER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT
+* OF LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING
+* THEREOF AND RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN
+* FRANCISCO, CA, UNDER THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE
+* (ICC).
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+*                         C O M P I L E R   F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                                 M A C R O S
+********************************************************************************
+*/
+#include <asm/mach-types.h>
+#include <linux/delay.h>
+#include <mach/gpio.h>
+#include <mach/io.h>
+#include <linux/platform_device.h>
+
+#if CONFIG_HAS_WAKELOCK
+#include <linux/wakelock.h>
+#define CFG_WMT_WAKELOCK_SUPPORT 1
+#endif
+
+
+#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
+********************************************************************************
+*/
+
+/*header files*/
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/spinlock.h>
+
+/* MTK_WCN_COMBO header files */
+#include "wmt_plat.h"
+#include "wmt_exp.h"
+#include "mtk_wcn_cmb_hw.h"
+
+/*******************************************************************************
+*                              C O N S T A N T S
+********************************************************************************
+*/
+
+
+#define GPIO_MT6620_PMUEN              XXX
+#define GPIO_MT6620_SYSRST             XXX
+#define GPIO_MT6620_LDO_EN     XXX
+#define INT_6620              XXX
+
+/*******************************************************************************
+*                             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_func_ctrl (UINT32 type, UINT32 on);
+static VOID wmt_plat_bgf_eirq_cb (VOID);
+
+static INT32 wmt_plat_ldo_ctrl (ENUM_PIN_STATE state);
+static INT32 wmt_plat_pmu_ctrl (ENUM_PIN_STATE state);
+static INT32 wmt_plat_rtc_ctrl (ENUM_PIN_STATE state);
+static INT32 wmt_plat_rst_ctrl (ENUM_PIN_STATE state);
+static INT32 wmt_plat_bgf_eint_ctrl (ENUM_PIN_STATE state);
+static INT32 wmt_plat_wifi_eint_ctrl (ENUM_PIN_STATE state);
+static INT32 wmt_plat_all_eint_ctrl (ENUM_PIN_STATE state);
+static INT32 wmt_plat_uart_ctrl (ENUM_PIN_STATE state);
+static INT32 wmt_plat_pcm_ctrl (ENUM_PIN_STATE state);
+static INT32 wmt_plat_i2s_ctrl (ENUM_PIN_STATE state);
+static INT32 wmt_plat_sdio_pin_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 gWmtDbgLvl = WMT_LOG_INFO;
+
+unsigned int g_balance_flag;
+spinlock_t g_balance_lock;
+unsigned int g_bgf_irq = INT_6620;//bgf eint number
+/*******************************************************************************
+*                           P R I V A T E   D A T A
+********************************************************************************
+*/
+
+
+
+
+#if CFG_WMT_WAKELOCK_SUPPORT
+static OSAL_SLEEPABLE_LOCK gOsSLock;
+static struct wake_lock wmtWakeLock;
+#endif
+
+irq_cb wmt_plat_bgf_irq_cb = NULL;
+device_audio_if_cb wmt_plat_audio_if_cb = NULL;
+const static fp_set_pin gfp_set_pin_table[] =
+{
+    [PIN_LDO] = wmt_plat_ldo_ctrl,
+    [PIN_PMU] = wmt_plat_pmu_ctrl,
+    [PIN_RTC] = wmt_plat_rtc_ctrl,
+    [PIN_RST] = wmt_plat_rst_ctrl,
+    [PIN_BGF_EINT] = wmt_plat_bgf_eint_ctrl,
+    [PIN_WIFI_EINT] = wmt_plat_wifi_eint_ctrl,
+    [PIN_ALL_EINT] = wmt_plat_all_eint_ctrl,
+    [PIN_UART_GRP] = wmt_plat_uart_ctrl,
+    [PIN_PCM_GRP] = wmt_plat_pcm_ctrl,
+    [PIN_I2S_GRP] = wmt_plat_i2s_ctrl,
+    [PIN_SDIO_GRP] = wmt_plat_sdio_pin_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;
+
+    /* input sanity check */
+    if ( (CMB_STUB_AIF_MAX <= state)
+        || (CMB_STUB_AIF_CTRL_MAX <= ctrl) ) {
+        iRet = -1;
+        WMT_ERR_FUNC("WMT-PLAT: invalid para, state(%d), ctrl(%d),iRet(%d) \n", state, ctrl, iRet);
+        return iRet;
+    }
+    if (0/*I2S/PCM share pin*/) {
+        // TODO: [FixMe][GeorgeKuo] how about MT6575? The following is applied to MT6573E1 only!!
+        pinShare = 1;
+        WMT_INFO_FUNC( "PCM/I2S pin share\n");
+    }
+    else{ //E1 later
+        pinShare = 0;
+        WMT_INFO_FUNC( "PCM/I2S pin seperate\n");
+    }
+
+    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_PCM_GRP, PIN_STA_DEINIT);
+        iRet += wmt_plat_gpio_ctrl(PIN_I2S_GRP, PIN_STA_DEINIT);
+        break;
+
+    case CMB_STUB_AIF_1:
+        iRet += wmt_plat_gpio_ctrl(PIN_PCM_GRP, PIN_STA_INIT);
+        iRet += wmt_plat_gpio_ctrl(PIN_I2S_GRP, PIN_STA_DEINIT);
+        break;
+
+    case CMB_STUB_AIF_2:
+        iRet += wmt_plat_gpio_ctrl(PIN_PCM_GRP, PIN_STA_DEINIT);
+        iRet += wmt_plat_gpio_ctrl(PIN_I2S_GRP, PIN_STA_INIT);
+        break;
+
+    case CMB_STUB_AIF_3:
+        iRet += wmt_plat_gpio_ctrl(PIN_PCM_GRP, PIN_STA_INIT);
+        iRet += wmt_plat_gpio_ctrl(PIN_I2S_GRP, PIN_STA_INIT);
+        break;
+
+    default:
+        /* FIXME: move to cust folder? */
+        WMT_ERR_FUNC("invalid state [%d]\n", state);
+        return -1;
+        break;
+    }
+
+    if (CMB_STUB_AIF_CTRL_EN == ctrl) {
+        WMT_INFO_FUNC("call chip aif setting \n");
+        /* need to control chip side GPIO */
+        //iRet += wmt_lib_set_aif(state, (pinShare) ? MTK_WCN_BOOL_TRUE : MTK_WCN_BOOL_FALSE);
+               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_WARN_FUNC("wmt_plat_audio_if_cb is not registered \n");
+                   iRet -= 1;
+               }
+    }
+    else {
+        WMT_INFO_FUNC("skip chip aif setting \n");
+    }
+    return iRet;
+
+}
+
+#if CFG_WMT_PS_SUPPORT
+irqreturn_t irq_handler(int i, void *arg)
+{
+    wmt_plat_bgf_eirq_cb();
+    return IRQ_HANDLED;
+}
+#endif
+
+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_WARN_FUNC("WMT-PLAT: wmt_plat_bgf_irq_cb not registered\n");
+               }
+#else
+               return;
+#endif
+}
+
+
+
+VOID wmt_lib_plat_irq_cb_reg (irq_cb bgf_irq_cb)
+{
+    wmt_plat_bgf_irq_cb = bgf_irq_cb;
+}
+
+VOID wmt_lib_plat_aif_cb_reg (device_audio_if_cb aif_ctrl_cb)
+{
+    wmt_plat_audio_if_cb = aif_ctrl_cb;
+}
+
+
+
+
+
+
+INT32
+wmt_plat_init (P_PWR_SEQ_TIME pPwrSeqTime)
+{
+    //CMB_STUB_CB stub_cb;
+    /*PWR_SEQ_TIME pwr_seq_time;*/
+    INT32 iret;
+
+    //stub_cb.aif_ctrl_cb = wmt_plat_audio_ctrl;
+    //stub_cb.func_ctrl_cb = wmt_plat_func_ctrl;
+    //stub_cb.size = sizeof(stub_cb);
+
+    /* register to cmb_stub */
+    //iret = mtk_wcn_cmb_stub_reg(&stub_cb);
+
+    /* init cmb_hw */
+    iret += mtk_wcn_cmb_hw_init(pPwrSeqTime);
+
+    /*init wmt function ctrl wakelock if wake lock is supported by host platform*/
+    #ifdef CFG_WMT_WAKELOCK_SUPPORT
+    wake_lock_init(&wmtWakeLock, WAKE_LOCK_SUSPEND, "wmtFuncCtrl");
+    osal_sleepable_lock_init(&gOsSLock);
+    #endif
+
+    spin_lock_init(&g_balance_lock);
+
+    WMT_DBG_FUNC("WMT-PLAT: ALPS platform init (%d)\n", iret);
+
+    return 0;
+}
+
+
+INT32
+wmt_plat_deinit (VOID)
+{
+    INT32 iret;
+
+    /* 1. de-init cmb_hw */
+    iret = mtk_wcn_cmb_hw_deinit();
+    /* 2. unreg to cmb_stub */
+    iret += mtk_wcn_cmb_stub_unreg();
+    /*3. wmt wakelock deinit*/
+    #ifdef CFG_WMT_WAKELOCK_SUPPORT
+    wake_lock_destroy(&wmtWakeLock);
+    osal_sleepable_lock_deinit(&gOsSLock);
+    WMT_DBG_FUNC("destroy wmtWakeLock\n");
+    #endif
+    WMT_DBG_FUNC("WMT-PLAT: ALPS platform init (%d)\n", iret);
+
+    return 0;
+}
+
+INT32 wmt_plat_sdio_ctrl (WMT_SDIO_SLOT_NUM sdioPortType, ENUM_FUNC_STATE on)
+{
+    if (FUNC_OFF == on)  {
+        /* add control logic here to generate SDIO CARD REMOVAL event to mmc/sd
+         * controller. SDIO card removal operation and remove success messages
+         * are expected.
+         */
+    }
+    else {
+        /* add control logic here to generate SDIO CARD INSERTION event to mmc/sd
+         * controller. SDIO card detection operation and detect success messages
+         * are expected.
+         */
+    }
+    return 0;
+}
+
+#if 0
+INT32
+wmt_plat_irq_ctrl (
+    ENUM_FUNC_STATE state
+    )
+{
+    return -1;
+}
+#endif
+
+static INT32
+wmt_plat_dump_pin_conf (VOID)
+{
+    WMT_INFO_FUNC( "[WMT-PLAT]=>dump wmt pin configuration start<=\n");
+    WMT_INFO_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_cmb_hw_pwr_on();
+        break;
+
+    case FUNC_OFF:
+        ret = mtk_wcn_cmb_hw_pwr_off();
+        break;
+
+    case FUNC_RST:
+        ret = mtk_wcn_cmb_hw_rst();
+        break;
+
+    default:
+        WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) in pwr_ctrl\n", state);
+        break;
+    }
+
+    return ret;
+}
+
+INT32 wmt_plat_ps_ctrl (ENUM_FUNC_STATE state)
+{
+    return -1;
+}
+
+INT32
+wmt_plat_eirq_ctrl (
+    ENUM_PIN_ID id,
+    ENUM_PIN_STATE state
+    )
+{
+    INT32 iRet;
+    unsigned int flags;
+    // 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 ) ) {
+        iRet = -1;
+        WMT_WARN_FUNC("WMT-PLAT:invalid PIN_STATE(%d) in eirq_ctrl for PIN(%d), ret(%d) \n", state, id, iRet);
+        return iRet;
+    }
+
+    iRet = -2;
+    switch (id) {
+    case PIN_BGF_EINT:
+        if (PIN_STA_INIT == state) {
+            /*request irq,low level triggered*/
+       iRet = request_irq(INT_6620, irq_handler,  IRQF_TRIGGER_LOW | IRQF_DISABLED, "MTK6620_BT", NULL);
+               
+           
+           g_balance_flag = 1;//do not modify this value
+            WMT_INFO_FUNC("WMT-PLAT:BGFInt (init) \n");
+        }
+        else if (PIN_STA_EINT_EN == state) {
+            /*enable irq*/
+           spin_lock_irqsave(&g_balance_lock,flags);
+           if(g_balance_flag)
+           {
+               /*if enter this case, the bgf eint has been enabled,so skip it.*/
+               WMT_INFO_FUNC("BGF_EINT has been enabled,g_balance_flag(%d)!\n",g_balance_flag);
+           }
+           else
+           {
+               /*do real irq enable implement is this case*/
+                   enable_irq(INT_6620);
+               g_balance_flag++;
+                WMT_INFO_FUNC("WMT-PLAT:BGFInt (en),g_balance_flag(%d)\n",g_balance_flag);
+           }
+           spin_unlock_irqrestore(&g_balance_lock,flags);
+        }
+        else if (PIN_STA_EINT_DIS == state) {
+            /*disable irq*/
+           spin_lock_irqsave(&g_balance_lock,flags);
+           if(!g_balance_flag)
+           {
+               /*if enter this case, the bgf eint has been disabled,so skip it.*/
+               WMT_INFO_FUNC("BGF_EINT has been disabled,g_balance_flag(%d)!\n",g_balance_flag);
+            }
+           else
+           {
+               /*do real irq disable implement is this case*/
+                   disable_irq_nosync(INT_6620);
+               g_balance_flag--;
+                WMT_INFO_FUNC("WMT-PLAT:BGFInt (dis) g_balance_flag(%d)\n",g_balance_flag);
+           }
+           spin_unlock_irqrestore(&g_balance_lock,flags);
+        }
+        else {
+            /* de-init: free irq*/
+            free_irq(INT_6620,NULL);
+            WMT_INFO_FUNC("WMT-PLAT:BGFInt (deinit) \n");
+
+        }
+        iRet = 0;
+        break;
+
+    case PIN_ALL_EINT:
+#if 0
+        if (PIN_STA_INIT == state) {
+
+            WMT_DBG_FUNC("WMT-PLAT:ALLInt (INIT but not used yet) \n");
+        }
+        else if (PIN_STA_EINT_EN == state) {
+             WMT_DBG_FUNC("WMT-PLAT:ALLInt (EN but not used yet) \n");
+        }
+        else if (PIN_STA_EINT_DIS == state) {
+            WMT_DBG_FUNC("WMT-PLAT:ALLInt (DIS but not used yet) \n");
+        }
+        else {
+
+            WMT_DBG_FUNC("WMT-PLAT:ALLInt (DEINIT but not used yet) \n");
+            /* de-init: nothing to do in ALPS, such as un-registration... */
+        }
+#else
+        WMT_DBG_FUNC("WMT-PLAT:ALLInt (not used yet) \n");
+#endif
+        iRet = 0;
+        break;
+
+    default:
+        WMT_WARN_FUNC("WMT-PLAT:unsupported EIRQ(PIN_ID:%d) in eirq_ctrl, ret (%d)\n", id, iRet);
+        iRet = -1;
+        break;
+    }
+
+    return iRet;
+
+}
+
+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 */
+        }
+        else {
+            WMT_WARN_FUNC("WMT-PLAT: null fp for gpio_ctrl(%d)\n", id);
+            return -2;
+        }
+    }
+       WMT_ERR_FUNC("WMT-PLAT:[out of range] id(%d), state (%d)\n", id, state);
+    return -1;
+}
+
+INT32
+wmt_plat_ldo_ctrl (
+    ENUM_PIN_STATE state
+    )
+{
+    switch(state)
+    {
+    case PIN_STA_INIT:
+        /*set to gpio output low, disable pull*/
+        WMT_DBG_FUNC("WMT-PLAT:LDO init (out 0) \n");
+        break;
+
+    case PIN_STA_OUT_H:
+        WMT_DBG_FUNC("WMT-PLAT:LDO (out 1) \n");
+        break;
+
+    case PIN_STA_OUT_L:
+        WMT_DBG_FUNC("WMT-PLAT:LDO (out 0) \n");
+        break;
+
+    case PIN_STA_IN_L:
+    case PIN_STA_DEINIT:
+        /*set to gpio input low, pull down enable*/
+        WMT_DBG_FUNC("WMT-PLAT:LDO deinit (in pd) \n");
+        break;
+
+    default:
+        WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on LDO\n", state);
+        break;
+    }
+    return 0;
+}
+
+INT32
+wmt_plat_pmu_ctrl (
+    ENUM_PIN_STATE state
+    )
+{
+    switch(state)
+    {
+    case PIN_STA_INIT:
+        /*set to gpio output low, disable pull*/
+       
+       printk("WMT-PLAT:PMU init (out 0) \n");
+        break;
+
+    case PIN_STA_OUT_H:
+       
+        printk("WMT-PLAT:PMU (out 1) \n");
+        break;
+
+    case PIN_STA_OUT_L:
+       
+        printk("WMT-PLAT:PMU (out 0) \n");
+        break;
+
+    case PIN_STA_IN_L:
+    case PIN_STA_DEINIT:
+        /*set to gpio input low, pull down enable*/
+       
+        printk("WMT-PLAT:PMU deinit (in pd) \n");
+        break;
+
+    default:
+        printk("WMT-PLAT:Warnning, invalid state(%d) on PMU\n", state);
+        break;
+    }
+
+    return 0;
+}
+
+INT32
+wmt_plat_rtc_ctrl (
+    ENUM_PIN_STATE state
+    )
+{
+    switch(state)
+    {
+    case PIN_STA_INIT:
+        WMT_DBG_FUNC("WMT-PLAT:RTC init \n");
+        break;
+
+    default:
+        WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on RTC\n", state);
+        break;
+    }
+    return 0;
+}
+
+
+INT32
+wmt_plat_rst_ctrl (
+    ENUM_PIN_STATE state
+    )
+{
+    switch(state)
+    {
+        case PIN_STA_INIT:
+            /*set to gpio output low, disable pull*/
+
+            printk("WMT-PLAT:RST init (out 0) \n");
+            break;
+
+        case PIN_STA_OUT_H:
+
+            printk("WMT-PLAT:RST (out 1) \n");
+            break;
+
+        case PIN_STA_OUT_L:
+
+            printk("WMT-PLAT:RST (out 0) \n");
+            break;
+
+        case PIN_STA_IN_L:
+        case PIN_STA_DEINIT:
+            /*set to gpio input low, pull down enable*/
+
+            printk("WMT-PLAT:RST deinit (in pd) \n");
+            break;
+
+        default:
+            printk("WMT-PLAT:Warnning, invalid state(%d) on RST\n", state);
+            break;
+    }
+
+    return 0;
+}
+
+INT32
+wmt_plat_bgf_eint_ctrl (
+    ENUM_PIN_STATE state
+    )
+{
+
+    switch(state)
+    {
+        case PIN_STA_INIT:
+            /*set to gpio input low, pull down eanble*/
+
+            WMT_DBG_FUNC("WMT-PLAT:BGFInt init(in pd) \n");
+            break;
+
+        case PIN_STA_MUX:
+            /* first: set to EINT mode,interrupt input, pull up enable*/
+
+            WMT_DBG_FUNC("WMT-PLAT:BGFInt mux (eint) \n");
+
+           /* second: enable bgf irq wake up host function*/
+            do {
+                int iret;
+                iret = enable_irq_wake(g_bgf_irq);//enable bgf irq wake up host function
+                WMT_INFO_FUNC("enable_irq_wake(bgf:%d)++, ret(%d)\n", g_bgf_irq, iret);
+            } while (0);
+            break;
+
+        case PIN_STA_IN_L:
+        case PIN_STA_DEINIT:
+           /* first: disable bgf irq wake up host function*/
+            do {
+                int iret;
+                iret = disable_irq_wake(g_bgf_irq);//disable bgf irq wake up host function
+                if (iret) {
+                    WMT_WARN_FUNC("disable_irq_wake(bgf:%d) fail(%d)\n", g_bgf_irq, iret);
+                    iret = 0;
+                }
+                else {
+                    WMT_INFO_FUNC("disable_irq_wake(bgf:%d)--, ret(%d)\n", g_bgf_irq, iret);
+                }
+            } while (0);
+
+           /* second: set to gpio input low, pull down enable*/
+            WMT_DBG_FUNC("WMT-PLAT:BGFInt deinit(in pd) \n");
+            break;
+
+        default:
+            WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on BGF EINT\n", state);
+            break;
+    }
+
+    return 0;
+}
+
+
+INT32 wmt_plat_wifi_eint_ctrl(ENUM_PIN_STATE state)
+{
+#if 0
+    switch(state)
+    {
+        case PIN_STA_INIT:
+            break;
+        case PIN_STA_MUX:
+
+            break;
+        case PIN_STA_EINT_EN:
+            break;
+        case PIN_STA_EINT_DIS:
+            break;
+        case PIN_STA_IN_L:
+        case PIN_STA_DEINIT:
+            /*set to gpio input low, pull down enable*/
+            break;
+        default:
+            WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on WIFI EINT\n", state);
+            break;
+    }
+#else
+    WMT_INFO_FUNC("WMT-PLAT:WIFI EINT is controlled by MSDC driver \n");
+#endif
+    return 0;
+}
+
+
+INT32
+wmt_plat_all_eint_ctrl (
+    ENUM_PIN_STATE state
+    )
+{
+    switch(state)
+    {
+        case PIN_STA_INIT:
+                 /*set to gpio input low, pull down eanble*/
+            WMT_DBG_FUNC("WMT-PLAT:ALLInt init(in pd) \n");
+            break;
+
+        case PIN_STA_MUX:
+                 /*set to gpio EINT mode, pull down enable*/
+            break;
+
+        case PIN_STA_IN_L:
+        case PIN_STA_DEINIT:
+            /*set to gpio input low, pull down enable*/
+            break;
+
+        default:
+            WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on ALL EINT\n", state);
+            break;
+    }
+    return 0;
+}
+
+INT32 wmt_plat_uart_ctrl(ENUM_PIN_STATE state)
+{
+    switch(state)
+    {
+    case PIN_STA_MUX:
+    case PIN_STA_INIT:
+        WMT_DBG_FUNC("WMT-PLAT:UART init (mode_01, uart) \n");
+        break;
+    case PIN_STA_IN_L:
+    case PIN_STA_DEINIT:
+        WMT_DBG_FUNC("WMT-PLAT:UART deinit (out 0) \n");
+        break;
+
+    default:
+        WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on UART Group\n", state);
+        break;
+    }
+
+    return 0;
+}
+
+
+INT32 wmt_plat_pcm_ctrl(ENUM_PIN_STATE state)
+{
+    switch(state)
+    {
+    case PIN_STA_MUX:
+    case PIN_STA_INIT:
+         /*set to PCM function*/
+        WMT_DBG_FUNC("WMT-PLAT:PCM init (pcm) \n");
+        break;
+
+    case PIN_STA_IN_L:
+    case PIN_STA_DEINIT:
+        WMT_DBG_FUNC("WMT-PLAT:PCM deinit (out 0) \n");
+        break;
+
+    default:
+        WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on PCM Group\n", state);
+        break;
+    }
+    return 0;
+}
+
+
+INT32 wmt_plat_i2s_ctrl(ENUM_PIN_STATE state)
+{
+#ifndef FM_ANALOG_INPUT
+    switch(state)
+    {
+    case PIN_STA_INIT:
+    case PIN_STA_MUX:
+    /*set to I2S function*/
+        WMT_DBG_FUNC("WMT-PLAT:I2S init \n");
+        break;
+    case PIN_STA_IN_L:
+    case PIN_STA_DEINIT:
+    /*set to gpio input low, pull down enable*/
+        WMT_DBG_FUNC("WMT-PLAT:I2S deinit (out 0) \n");
+        break;
+    default:
+        WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on I2S Group\n", state);
+        break;
+    }
+#else
+        WMT_INFO_FUNC( "[MT6620]warnning:FM analog mode is set, no I2S GPIO settings should be modified by combo driver\n");
+#endif
+
+    return 0;
+}
+
+INT32
+wmt_plat_sdio_pin_ctrl (
+    ENUM_PIN_STATE state
+    )
+{
+    switch (state) {
+    case PIN_STA_INIT:
+    case PIN_STA_MUX:
+        break;
+    case PIN_STA_DEINIT:
+        break;
+    default:
+        WMT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on SDIO Group\n", state);
+        break;
+    }
+    return 0;
+}
+
+static INT32
+wmt_plat_gps_sync_ctrl (
+    ENUM_PIN_STATE state
+    )
+{
+    switch (state) {
+    case PIN_STA_INIT:
+    case PIN_STA_DEINIT:
+    /*set GPS_SYNC GPIO to GPIO mode, pull disable,output low*/
+        break;
+
+    case PIN_STA_MUX:
+    /*set GPS_SYNC GPIO to GPS_SYNC function*/
+        break;
+
+    default:
+        break;
+    }
+    return 0;
+}
+
+
+static INT32
+wmt_plat_gps_lna_ctrl (
+        ENUM_PIN_STATE state
+        )
+{
+    switch (state) {
+    case PIN_STA_INIT:
+    case PIN_STA_DEINIT:
+    /*set GPS_LNA GPIO to GPIO mode, pull disable,output low*/
+        break;
+    case PIN_STA_OUT_H:
+    /*set GPS_LNA GPIO to GPIO mode, pull disable,output high*/
+        break;
+    case PIN_STA_OUT_L:
+    /*set GPS_LNA GPIO to GPIO mode, pull disable,output low*/
+        break;
+
+    default:
+        WMT_WARN_FUNC("%d mode not defined for  gps lna pin !!!\n", state);
+        break;
+    }
+    return 0;
+
+}
+
+
+
+INT32 wmt_plat_wake_lock_ctrl(ENUM_WL_OP opId)
+{
+#ifdef CFG_WMT_WAKELOCK_SUPPORT
+    static INT32 counter = 0;
+
+
+    osal_lock_sleepable_lock( &gOsSLock);
+    if (WL_OP_GET == opId)
+    {
+        ++counter;
+    }else if (WL_OP_PUT == opId)
+    {
+        --counter;
+    }
+    osal_unlock_sleepable_lock( &gOsSLock);
+    if (WL_OP_GET == opId && counter == 1)
+    {
+        wake_lock(&wmtWakeLock);
+        WMT_DBG_FUNC("WMT-PLAT: after wake_lock(%d), counter(%d)\n", wake_lock_active(&wmtWakeLock), counter);
+
+    }
+    else if (WL_OP_PUT == opId && counter == 0)
+    {
+        wake_unlock(&wmtWakeLock);
+        WMT_DBG_FUNC("WMT-PLAT: after wake_unlock(%d), counter(%d)\n", wake_lock_active(&wmtWakeLock), counter);
+    }
+    else
+    {
+        WMT_WARN_FUNC("WMT-PLAT: wakelock status(%d), counter(%d)\n", wake_lock_active(&wmtWakeLock), counter);
+    }
+    return 0;
+#else
+    WMT_WARN_FUNC("WMT-PLAT: host awake function is not supported.");
+    return 0;
+
+#endif
+}
+
diff --git a/drivers/mtk_wcn_combo/common/platform/sample/wmt_plat_stub.c b/drivers/mtk_wcn_combo/common/platform/sample/wmt_plat_stub.c
new file mode 100755 (executable)
index 0000000..bcb1380
--- /dev/null
@@ -0,0 +1,110 @@
+/*! \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
+********************************************************************************
+*/
+
+
+#if CONFIG_HAS_WAKELOCK
+#include <linux/wakelock.h>
+#define CFG_WMT_WAKELOCK_SUPPORT 1
+#endif
+
+#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
+********************************************************************************
+*/
+
+/* ALPS and COMBO header files */
+#include <mach/mtk_wcn_cmb_stub.h>
+
+/* MTK_WCN_COMBO header files */
+#include "wmt_plat.h"
+#include "wmt_plat_stub.h"
+#include "wmt_exp.h"
+#include <mach/mtk_wcn_cmb_stub.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
+********************************************************************************
+*/
+
+static VOID wmt_plat_func_ctrl (UINT32 type, UINT32 on);
+
+
+
+/*******************************************************************************
+*                            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 S
+********************************************************************************
+*/
+
+static VOID wmt_plat_func_ctrl (UINT32 type, UINT32 on)
+{
+    if (on) {
+        mtk_wcn_wmt_func_on((ENUM_WMTDRV_TYPE_T)type);
+    }
+    else {
+        mtk_wcn_wmt_func_off((ENUM_WMTDRV_TYPE_T)type);
+    }
+    return;
+}
+
+
+INT32 wmt_plat_stub_init (void)
+{
+    INT32 iRet = -1;
+    CMB_STUB_CB stub_cb;
+    stub_cb.aif_ctrl_cb = wmt_plat_audio_ctrl;
+    stub_cb.func_ctrl_cb = wmt_plat_func_ctrl;
+    stub_cb.size = sizeof(stub_cb);
+
+    /* register to cmb_stub */
+    iRet = mtk_wcn_cmb_stub_reg(&stub_cb);
+    return iRet;
+}
+
+
diff --git a/drivers/mtk_wcn_combo/drv_bt/Makefile b/drivers/mtk_wcn_combo/drv_bt/Makefile
new file mode 100755 (executable)
index 0000000..9cd070a
--- /dev/null
@@ -0,0 +1,43 @@
+# Copyright Statement:
+#
+# This software/firmware and related documentation ("MediaTek Software") are
+# protected under relevant copyright laws. The information contained herein
+# is confidential and proprietary to MediaTek Inc. and/or its licensors.
+# Without the prior written permission of MediaTek inc. and/or its licensors,
+# any reproduction, modification, use or disclosure of MediaTek Software,
+# and information contained herein, in whole or in part, shall be strictly prohibited.
+#
+# MediaTek Inc. (C) 2010. All rights reserved.
+#
+# BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+# THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+# RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+# AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+# NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+# SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+# SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+# THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+# THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+# CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+# SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+# STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+# CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+# AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+# OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+# MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+#
+# The following software/firmware and/or related documentation ("MediaTek Software")
+# have been modified by MediaTek Inc. All revisions are subject to any receiver's
+# applicable license agreements with MediaTek Inc.
+
+
+#
+# Makefile for the Linux Bluetooth HCI device drivers.
+#
+ccflags-y := -I$(src)/include -I$(src)/../common/include -I$(src)/../common/linux/include 
+
+obj-$(CONFIG_MTK_COMBO_BT_HCI) += hci_stp.o
+hci_stp-objs   := linux/hci_stp.o
diff --git a/drivers/mtk_wcn_combo/drv_bt/include/bt_conf.h b/drivers/mtk_wcn_combo/drv_bt/include/bt_conf.h
new file mode 100755 (executable)
index 0000000..248fcf1
--- /dev/null
@@ -0,0 +1,45 @@
+/* Copyright Statement:\r
+ *\r
+ * This software/firmware and related documentation ("MediaTek Software") are\r
+ * protected under relevant copyright laws. The information contained herein\r
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.\r
+ * Without the prior written permission of MediaTek inc. and/or its licensors,\r
+ * any reproduction, modification, use or disclosure of MediaTek Software,\r
+ * and information contained herein, in whole or in part, shall be strictly prohibited.\r
+ *\r
+ * MediaTek Inc. (C) 2010. All rights reserved.\r
+ *\r
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES\r
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")\r
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON\r
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.\r
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE\r
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR\r
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH\r
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES\r
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES\r
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK\r
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR\r
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND\r
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,\r
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,\r
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO\r
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.\r
+ *\r
+ * The following software/firmware and/or related documentation ("MediaTek Software")\r
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's\r
+ * applicable license agreements with MediaTek Inc.\r
+ */\r
+\r
+static struct btradio_conf_data sDefaultCfg =\r
+{\r
+    {0x00, 0x00, 0x46, 0x66, 0x20, 0x01},\r
+    {0x60, 0x00},\r
+    {0x23, 0x10, 0x00, 0x00},\r
+    {0x06, 0x80, 0x00, 0x06, 0x03, 0x06},\r
+    {0x03, 0x40, 0x1F, 0x40, 0x1F, 0x00, 0x04},\r
+    {0x80, 0x00},\r
+    {0xFF, 0xFF, 0xFF}\r
+};
\ No newline at end of file
diff --git a/drivers/mtk_wcn_combo/drv_bt/include/hci_stp.h b/drivers/mtk_wcn_combo/drv_bt/include/hci_stp.h
new file mode 100755 (executable)
index 0000000..cff49c1
--- /dev/null
@@ -0,0 +1,172 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ * 
+ * MediaTek Inc. (C) 2010. All rights reserved.
+ * 
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+
+
+#ifndef _HCI_STP_H
+#define _HCI_STP_H
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/poll.h>
+
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/signal.h>
+#include <linux/ioctl.h>
+#include <linux/skbuff.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/fs.h>
+#include <asm/uaccess.h>
+
+/* debugging */
+#include <linux/time.h>
+#include <linux/delay.h>
+
+/* constant of kernel version */
+#include <linux/version.h>
+
+/* kthread APIs */
+#include <linux/kthread.h>
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+
+
+/*******************************************************************************
+*                         C O M P I L E R   F L A G S
+********************************************************************************
+*/
+
+#define HCI_STP_TX_TASKLET (0) /* do tx in a tasklet context */
+#define HCI_STP_TX_THRD (1) /* do tx in an init thread context */
+/* select tx context */
+#define HCI_STP_TX (HCI_STP_TX_THRD)
+
+
+#if (HCI_STP_TX == HCI_STP_TX_TASKLET)
+#define HCI_STP_TX_TASKLET_RWLOCK (0) /* use rwlock_t */
+#define HCI_STP_TX_TASKLET_SPINLOCK (1) /* use spinlock_t */
+/* select txq protection method */
+#define HCI_STP_TX_TASKLET_LOCK (HCI_STP_TX_TASKLET_SPINLOCK)
+#endif
+
+/* Flag to enable BD address auto-gen mechanism */
+/* Auto-gen address is illegal, default disabled */
+#define BD_ADDR_AUTOGEN (0)
+
+/*******************************************************************************
+*                              C O N S T A N T S
+********************************************************************************
+*/
+
+/* HCI-STP flag bits */
+#define HCI_STP_PROTO_SET (0)
+/* HCI-STP flag TX states bits */
+#define HCI_STP_SENDING (1)
+#define HCI_STP_TX_WAKEUP (2)
+
+/* maximum delay required, shall also consider possible delay on a busy system. */
+#define BT_CMD_DELAY_MS_COMM (100) /*(50)*/
+#define BT_CMD_DELAY_MS_RESET (600) /*(500)*/
+
+#define BT_CMD_DELAY_SAFE_GUARD (20) /*(2)*/
+
+/* HCI-STP safer hci_reset handling */
+#define HCI_STP_SAFE_RESET (1)
+
+/*******************************************************************************
+*                             D A T A   T Y P E S
+********************************************************************************
+*/
+struct hci_stp_init_cmd {
+    unsigned char *hci_cmd;
+    unsigned int cmdSz;
+    unsigned char *hci_evt;
+    unsigned int evtSz;
+    char *str;
+};
+
+struct hci_stp {
+    struct hci_dev *hdev;
+    unsigned long flags;
+
+    struct sk_buff_head txq; /* used to queue TX packets */
+    unsigned long tx_state;
+
+    struct work_struct init_work;
+    struct completion *p_init_comp;
+    wait_queue_head_t *p_init_evt_wq;
+    spinlock_t init_lock; /* protect init variables: comp and wq */
+    unsigned int init_cmd_idx;
+    int init_evt_rx_flag; /* init result of last sent cmd */
+
+#if HCI_STP_SAFE_RESET
+    wait_queue_head_t reset_wq;
+    atomic_t reset_count; /* !0: reset in progress */
+#endif
+    //void *priv; /* unused? */
+    //struct sk_buff *tx_skb; /* unused? */
+    //spinlock_t rx_lock; /* unused? */
+};
+
+struct btradio_conf_data {
+  unsigned char addr[6];
+  unsigned char voice[2];
+  unsigned char codec[4];
+  unsigned char radio[6];
+  unsigned char sleep[7];
+  unsigned char feature[2];
+  unsigned char tx_pwr_offset[3];
+};
+/*******************************************************************************
+*                                 M A C R O S
+********************************************************************************
+*/
+#define hci_stp_init_entry(c) \
+  {.hci_cmd=c, .cmdSz=sizeof(c), .hci_evt=c##_evt, .evtSz=sizeof(c##_evt), .str=#c}
+
+#endif /* end of _HCI_STP_H */
+
diff --git a/drivers/mtk_wcn_combo/drv_bt/linux/hci_stp.c b/drivers/mtk_wcn_combo/drv_bt/linux/hci_stp.c
new file mode 100755 (executable)
index 0000000..30d400a
--- /dev/null
@@ -0,0 +1,1589 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ * 
+ * MediaTek Inc. (C) 2010. All rights reserved.
+ * 
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+
+
+#include "hci_stp.h"
+#include "bt_conf.h"
+#include "stp_exp.h"
+#include "wmt_exp.h"
+
+/*******************************************************************************
+*                              C O N S T A N T S
+********************************************************************************
+*/
+
+/* Debugging Purpose */
+#define PFX "[HCI-STP]"
+#define BT_LOG_LOUD (4)
+#define BT_LOG_DBG (3)
+#define BT_LOG_INFO (2)
+#define BT_LOG_WARN (1)
+#define BT_LOG_ERR (0)
+
+#define VERSION "2.0"
+
+/* H4 receiver States */
+#define H4_W4_PACKET_TYPE (0)
+#define H4_W4_EVENT_HDR (1)
+#define H4_W4_ACL_HDR (2)
+#define H4_W4_SCO_HDR (3)
+#define H4_W4_DATA (4)
+
+#define HCI_STP_TXQ_IN_BLZ (0)
+/* access txq in BlueZ tx tasklet context */
+#define HCI_STP_TXQ_IN_HCISTP (1)
+/* access txq in HCI-STP context,  defined by compile flag: HCI_STP_TX */
+
+/*******************************************************************************
+*                            P U B L I C   D A T A
+********************************************************************************
+*/
+unsigned int gDbgLevel = BT_LOG_INFO;
+
+/*******************************************************************************
+*                           P R I V A T E   D A T A
+********************************************************************************
+*/
+/* Allow one BT driver */
+static struct hci_dev *hdev = NULL;
+static int reset = 0;
+
+/* maybe struct hci_stp is a better place to put these data */
+#if (HCI_STP_TX == HCI_STP_TX_TASKLET)
+static struct tasklet_struct hci_tx_tasklet;
+
+#if (HCI_STP_TX_TASKLET_LOCK == HCI_STP_TX_TASKLET_RWLOCK)
+static DEFINE_RWLOCK(hci_stp_txqlock);
+
+#elif (HCI_STP_TX_TASKLET_LOCK == HCI_STP_TX_TASKLET_SPINLOCK)
+static spinlock_t hci_stp_txqlock;
+
+#endif
+#endif
+
+#if (HCI_STP_TX == HCI_STP_TX_THRD)
+static spinlock_t hci_stp_txqlock;
+struct task_struct * hci_stp_tx_thrd = NULL;
+wait_queue_head_t hci_stp_tx_thrd_wq;
+#endif
+
+
+#define CUSTOM_BT_CFG_FILE          "/data/BT.cfg"
+#define INTERNAL_BT_CFG_FILE        "/data/bluetooth/BT.cfg"
+
+static bool fgetEFUSE = false;
+
+static unsigned char bt_get_bd_addr[4] =
+    {0x01, 0x09, 0x10, 0x00};
+static unsigned char bt_get_bd_addr_evt[] =
+    {0x04, 0x0E, 0x0A, 0x01, 0x09, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char bt_set_bd_addr[10] =
+    {0x01, 0x1A, 0xFC, 0x06, 0x01, 0x20, 0x66, 0x46, 0x00, 0x00};
+static unsigned char bt_set_bd_addr_evt[] =
+    {0x04, 0x0E, 0x04, 0x01, 0x1A, 0xFC, 0x00};
+static unsigned char bt_set_link_key_type[5]=
+    {0x01, 0x1B, 0xFC, 0x01, 0x01};
+static unsigned char bt_set_link_key_type_evt[] =
+    {0x04, 0x0E, 0x04, 0x01, 0x1B, 0xFC, 0x00};
+static unsigned char bt_set_unit_key[20] =
+    {0x01, 0x75, 0xFC, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char bt_set_unit_key_evt[] =
+    {0x04, 0x0E, 0x04, 0x01, 0x75, 0xFC, 0x00};
+static unsigned char bt_set_encrypt[7] =
+    {0x01, 0x76, 0xFC, 0x03, 0x00, 0x02, 0x10};
+static unsigned char bt_set_encrypt_evt[] =
+    {0x04, 0x0E, 0x04, 0x01, 0x76, 0xFC, 0x00};
+static unsigned char bt_set_pin_code_type[5] =
+    {0x01, 0x0A, 0x0C, 0x01, 0x00};
+static unsigned char bt_set_pin_code_type_evt[] =
+    {0x04, 0x0E, 0x04, 0x01, 0x0A, 0x0C, 0x00};
+static unsigned char bt_set_voice[6] =
+    {0x01, 0x26, 0x0C, 0x02, 0x60, 0x00};
+static unsigned char bt_set_voice_evt[] =
+    {0x04, 0x0E, 0x04, 0x01, 0x26, 0x0C, 0x00};
+static unsigned char bt_set_codec[8] =
+    {0x01, 0x72, 0xFC, 0x04, 0x23, 0x10, 0x00, 0x00};
+static unsigned char bt_set_codec_evt[] =
+    {0x04, 0x0E, 0x04, 0x01, 0x72, 0xFC, 0x00};
+static unsigned char bt_set_radio[10] =
+    {0x01, 0x79, 0xFC, 0x06, 0x06, 0x80, 0x00, 0x06, 0x03, 0x06};
+static unsigned char bt_set_radio_evt[] =
+    {0x04, 0x0E, 0x04, 0x01, 0x79, 0xFC, 0x00};
+static unsigned char bt_set_tx_pwr_offset[7] =
+    {0x01, 0x93, 0xFC, 0x03, 0xFF, 0xFF, 0xFF};
+static unsigned char bt_set_tx_pwr_offset_evt[] =
+    {0x04, 0x0E, 0x04, 0x01, 0x93, 0xFC, 0x00};
+static unsigned char bt_set_sleep[11] =
+    {0x01, 0x7A, 0xFC, 0x07, 0x03, 0x40, 0x1F, 0x40, 0x1F, 0x00, 0x04};
+static unsigned char bt_set_sleep_evt[] =
+    {0x04, 0x0E, 0x04, 0x01, 0x7A, 0xFC, 0x00};
+static unsigned char bt_set_feature[6] =
+    {0x01, 0x7D, 0xFC, 0x02, 0x80, 0x0};
+static unsigned char bt_set_feature_evt[] =
+    {0x04, 0x0E, 0x04, 0x01, 0x7D, 0xFC, 0x00};
+static unsigned char bt_set_OSC[9] =
+    {0x01, 0x7B, 0xFC, 0x05, 0x01, 0x01, 0x14, 0x0A, 0x05};
+static unsigned char bt_set_OSC_evt[] =
+    {0x04, 0x0E, 0x04, 0x01, 0x7B, 0xFC, 0x00};
+static unsigned char bt_set_LPO[14] =
+    {0x01, 0x7C, 0xFC, 0x0A, 0x01, 0xFA, 0x0A, 0x02, 0x00, 0xA6, 0x0E, 0x00, 0x40, 0x00};
+static unsigned char bt_set_LPO_evt[] =
+    {0x04, 0x0E, 0x04, 0x01, 0x7C, 0xFC, 0x00};
+static unsigned char bt_set_legacy_PTA[14] =
+    {0x01, 0x74, 0xFC, 0x0A, 0xC9, 0x8B, 0xBF, 0x00, 0x00, 0x52, 0x0E, 0x0E, 0x1F, 0x1B};
+static unsigned char bt_set_legacy_PTA_evt[] =
+    {0x04, 0x0E, 0x04, 0x01, 0x74, 0xFC, 0x00};
+static unsigned char bt_set_BLE_PTA[9] =
+    {0x01, 0xFC, 0xFC, 0x05, 0x16, 0x0E, 0x0E, 0x00, 0x07};
+static unsigned char bt_set_BLE_PTA_evt[] =
+    {0x04, 0x0E, 0x04, 0x01, 0xFC, 0xFC, 0x00};
+static unsigned char bt_set_RF_desence[10] =
+    {0x01, 0x20, 0xFC, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char bt_set_RF_desence_evt[] =
+    {0x04, 0x0e, 0x04, 0x01, 0x20, 0xFC, 0x00};
+static unsigned char bt_reset[4] =
+    {0x01, 0x03, 0x0C, 0x0};
+static unsigned char bt_reset_evt[] =
+    {0x04, 0x0E, 0x04, 0x01, 0x03, 0x0C, 0x00};
+static unsigned char bt_set_intern_PTA_1[19] =
+    {0x01, 0xFB, 0xFC, 0x0F, 0x00, 0x01, 0x0F, 0x0F, 0x01, 0x0F, 0x0F, 0x01, 0x0F, 0x0F, 0x01, 0x0F, 0x0F, 0x02, 0x01};
+static unsigned char bt_set_intern_PTA_1_evt[] =
+    {0x04, 0x0E, 0x04, 0x01, 0xFB, 0xFC, 0x00};
+static unsigned char bt_set_intern_PTA_2[11] =
+    {0x01, 0xFB, 0xFC, 0x07, 0x01, 0x19, 0x19, 0x07, 0xD0, 0x00, 0x01};
+static unsigned char bt_set_intern_PTA_2_evt[] =
+    {0x04, 0x0E, 0x04, 0x01, 0xFB, 0xFC, 0x00};
+static unsigned char bt_set_SLP_control_reg[12] =
+    {0x01, 0xD0, 0xFC, 0x08, 0x74, 0x00, 0x01, 0x81, 0xE2, 0x29, 0x0, 0x0};
+static unsigned char bt_set_SLP_control_reg_evt[] =
+    {0x04, 0x0E, 0x04, 0x01, 0xD0, 0xFC, 0x00};
+static unsigned char bt_set_SLP_LDOD_reg[12] =
+    {0x01, 0xD0, 0xFC, 0x08, 0x1C, 0x00, 0x02, 0x81, 0x79, 0x08, 0x0, 0x0};
+static unsigned char bt_set_SLP_LDOD_reg_evt[] =
+    {0x04, 0x0E, 0x04, 0x01, 0xD0, 0xFC, 0x00};
+static unsigned char bt_set_RF_reg_100[10] =
+    {0x01, 0xB0, 0xFC, 0x06, 0x64, 0x01, 0x02, 0x00, 0x00, 0x00};
+static unsigned char bt_set_RF_reg_100_evt[] =
+    {0x04, 0x0E, 0x04, 0x01, 0xB0, 0xFC, 0x00};
+
+/* Do init commands in sequence, cmd and cmd##_evt */
+static struct hci_stp_init_cmd init_table[] =
+{
+    hci_stp_init_entry(bt_get_bd_addr),
+    hci_stp_init_entry(bt_set_bd_addr),
+    hci_stp_init_entry(bt_set_link_key_type),
+    hci_stp_init_entry(bt_set_unit_key),
+    hci_stp_init_entry(bt_set_encrypt),
+    hci_stp_init_entry(bt_set_pin_code_type),
+    hci_stp_init_entry(bt_set_voice),
+    hci_stp_init_entry(bt_set_codec),
+    hci_stp_init_entry(bt_set_radio),
+    hci_stp_init_entry(bt_set_tx_pwr_offset),
+    hci_stp_init_entry(bt_set_sleep),
+    hci_stp_init_entry(bt_set_feature),
+    hci_stp_init_entry(bt_set_OSC),
+    hci_stp_init_entry(bt_set_LPO),
+    hci_stp_init_entry(bt_set_legacy_PTA),
+    hci_stp_init_entry(bt_set_BLE_PTA),
+    hci_stp_init_entry(bt_set_RF_desence),
+    hci_stp_init_entry(bt_reset),
+    hci_stp_init_entry(bt_set_intern_PTA_1),
+    hci_stp_init_entry(bt_set_intern_PTA_2),
+    hci_stp_init_entry(bt_set_SLP_control_reg),
+    hci_stp_init_entry(bt_set_SLP_LDOD_reg),
+    hci_stp_init_entry(bt_set_RF_reg_100),
+};
+
+/*******************************************************************************
+*                             D A T A   T Y P E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                                 M A C R O S
+********************************************************************************
+*/
+
+#define BT_LOUD_FUNC(fmt, arg...)   if(gDbgLevel >= BT_LOG_LOUD){printk(PFX "[L]%s:"  fmt, __FUNCTION__ ,##arg);}
+#define BT_DBG_FUNC(fmt, arg...)    if(gDbgLevel >= BT_LOG_DBG){printk(PFX "[D]%s:"  fmt, __FUNCTION__ ,##arg);}
+#define BT_INFO_FUNC(fmt, arg...)   if(gDbgLevel >= BT_LOG_INFO){printk(PFX "[I]%s:"  fmt, __FUNCTION__ ,##arg);}
+#define BT_WARN_FUNC(fmt, arg...)   if(gDbgLevel >= BT_LOG_WARN){printk(PFX "[W]%s:"  fmt, __FUNCTION__ ,##arg);}
+#define BT_ERR_FUNC(fmt, arg...)    if(gDbgLevel >= BT_LOG_ERR){printk(PFX "[E]%s:"   fmt, __FUNCTION__ ,##arg);}
+#define BT_TRC_FUNC(f)              if(gDbgLevel >= BT_LOG_LOUD){printk(PFX "[T]%s:%d\n", __FUNCTION__, __LINE__);}
+
+#if HCI_STP_SAFE_RESET
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
+/* HCI_RESET bit definition in linux/include/net/bluetooth/hci.h since 2.6.39:
+    http://lxr.free-electrons.com/source/include/net/bluetooth/hci.h?v=2.6.39;a=arm
+*/
+#define BT_GET_HDEV_RST_FG(hdev) (test_bit(HCI_RESET, &hdev->flags))
+#else
+#define BT_GET_HDEV_RST_FG(hdev) (0) /* no HCI_RESET bit available */
+#endif
+#endif
+
+/*******************************************************************************
+*                  F U N C T I O N   D E C L A R A T I O N S
+********************************************************************************
+*/
+/* Functions to be implemted by all HCI_STP_TX_* methods */
+void hci_stp_tx_init (struct hci_stp *hu);
+void hci_stp_tx_deinit (struct hci_stp *hu);
+void hci_stp_txq_lock (unsigned int ctx);
+void hci_stp_txq_unlock (unsigned int ctx);
+void hci_stp_tx_kick (void);
+
+/* Functions to be implemented by all HCI_STP_INIT_* methods*/
+static int hci_stp_dev_init (struct hci_stp *phu);
+
+#if (HCI_STP_TX == HCI_STP_TX_TASKLET)
+static int hci_stp_tx_wakeup (struct hci_stp *hu);
+static void hci_stp_tx_tasklet_func (unsigned long data);
+#endif
+
+#if (HCI_STP_TX == HCI_STP_TX_THRD)
+static int hci_stp_tx_thrd_func (void *pdata);
+#endif
+
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+
+static ssize_t file_read(char *filename, char *buf, size_t len, loff_t *offset)
+{
+    struct file *fp;
+    mm_segment_t old_fs;
+    ssize_t retLen;
+
+    fp = filp_open(filename, O_RDONLY, 0);
+    if (IS_ERR(fp)) {
+        BT_WARN_FUNC("Failed to open %s!\n", filename);
+        return -1;
+    }
+
+    old_fs = get_fs();
+    set_fs(KERNEL_DS);
+
+    if ((fp->f_op == NULL) || (fp->f_op->read == NULL)){
+        BT_WARN_FUNC("File can not be read!\n");
+        set_fs(old_fs);
+        filp_close(fp, NULL);
+        return -1;
+    }
+
+    retLen = fp->f_op->read(fp, buf, len, offset);
+
+    set_fs(old_fs);
+    filp_close(fp, NULL);
+
+    return retLen;
+}
+
+static ssize_t file_write(char *filename, char *buf, size_t len, loff_t *offset)
+{
+    struct file *fp;
+    mm_segment_t old_fs;
+    ssize_t retLen;
+
+    fp = filp_open(filename, O_WRONLY | O_CREAT, 0644);
+    if (IS_ERR(fp)) {
+        BT_WARN_FUNC("Failed to open %s!\n", filename);
+        return -1;
+    }
+
+    old_fs = get_fs();
+    set_fs(KERNEL_DS);
+
+    if ((fp->f_op == NULL) || (fp->f_op->write == NULL)){
+        BT_WARN_FUNC("File can not be write!\n");
+        set_fs(old_fs);
+        filp_close(fp, NULL);
+        return -1;
+    }
+
+    retLen = fp->f_op->write(fp, buf, len, offset);
+
+    set_fs(old_fs);
+    filp_close(fp, NULL);
+
+    return retLen;
+}
+
+int load_custom_bt_conf(struct btradio_conf_data *cfg)
+{
+   /*
+    This method depends on customer's platform configuration data
+    store machenism.
+    Customer may use NVRAM, data file, or other patterns.
+    Here RECOMMEND and GIVE AN EXAMPLE to push configuration data
+    under /data/BT.cfg
+    */
+
+    struct btradio_conf_data temp;
+    loff_t pos = 0;
+    ssize_t retLen;
+
+    retLen = file_read(CUSTOM_BT_CFG_FILE,
+                       (char*)&temp,
+                       sizeof(temp),
+                       &pos);
+
+    if (retLen < 0)
+        return -1;
+
+    if(retLen < sizeof(temp)){
+        BT_ERR_FUNC("File read error len: %d\n", retLen);
+        return -1;
+    }
+    else{
+        memcpy(cfg, &temp, retLen);
+        return 0;
+    }
+}
+
+int load_internal_bt_conf(struct btradio_conf_data *cfg)
+{
+    struct btradio_conf_data temp;
+    loff_t pos = 0;
+    ssize_t retLen;
+    ssize_t written;
+
+    retLen = file_read(INTERNAL_BT_CFG_FILE,
+                       (char*)&temp,
+                       sizeof(temp),
+                       &pos);
+
+    if (retLen < 0){
+        BT_INFO_FUNC("No internal BT config, generate from default value\n");
+        memcpy(&temp, &sDefaultCfg, sizeof(struct btradio_conf_data));
+
+        // Generate internal BT config file
+        pos = 0;
+        written = file_write(INTERNAL_BT_CFG_FILE,
+                             (char*)&temp,
+                             sizeof(temp),
+                             &pos);
+        if (written < 0){
+            BT_ERR_FUNC("Try to create internal BT config, error\n");
+            return -1;
+        }
+        else if(written < sizeof(temp)){
+            BT_ERR_FUNC("File write error len: %d\n", written);
+        }
+        else{
+            BT_INFO_FUNC("Internal BT config generated\n");
+        }
+
+        memcpy(cfg, &temp, sizeof(temp));
+        return 0;
+    }
+    else if(retLen < sizeof(temp)){
+        BT_ERR_FUNC("File read error len: %d\n", retLen);
+    }
+
+    memcpy(cfg, &temp, retLen);
+    return 0;
+}
+
+
+static inline void hci_stp_tx_skb_comp (struct hci_stp *hu, struct sk_buff *skb)
+{
+    struct hci_dev *hdev;
+    int pkt_type;
+
+
+    hdev = hu->hdev;
+    hdev->stat.byte_tx += skb->len;
+
+    pkt_type = bt_cb(skb)->pkt_type;
+    /* Update HCI stat counters */
+    switch (pkt_type) {
+       case HCI_COMMAND_PKT:
+            hdev->stat.cmd_tx++;
+            break;
+
+       case HCI_ACLDATA_PKT:
+            hdev->stat.acl_tx++;
+            break;
+
+       case HCI_SCODATA_PKT:
+            hdev->stat.cmd_tx++;
+            break;
+    }
+}
+
+#if (HCI_STP_TX == HCI_STP_TX_TASKLET)
+void hci_stp_tx_init (struct hci_stp *hu)
+{
+    tasklet_init(&hci_tx_tasklet, hci_stp_tx_tasklet_func, (unsigned long)hu);
+
+    #if (HCI_STP_TX_TASKLET_LOCK == HCI_STP_TX_TASKLET_RWLOCK)
+    rwlock_init(&hci_stp_txqlock);
+    #elif (HCI_STP_TX_TASKLET_LOCK == HCI_STP_TX_TASKLET_SPINLOCK)
+    spin_lock_init(&hci_stp_txqlock);
+    #endif
+}
+
+void hci_stp_tx_deinit (struct hci_stp *hu)
+{
+    tasklet_kill(&hci_tx_tasklet);
+
+    return;
+}
+
+void hci_stp_txq_lock (unsigned int ctx)
+{
+    if (ctx == HCI_STP_TXQ_IN_BLZ) {
+        /* lock txq in BlueZ tx tasklet context */
+    #if (HCI_STP_TX_TASKLET_LOCK == HCI_STP_TX_TASKLET_RWLOCK)
+        write_lock_bh(&hci_stp_txqlock);
+    #elif (HCI_STP_TX_TASKLET_LOCK == HCI_STP_TX_TASKLET_SPINLOCK)
+        spin_lock_bh(&hci_stp_txqlock);
+    #else
+    #error "HCI_STP_TX_TASKLET_LOCK"
+    #endif
+    }
+    else {
+        /* lock txq in HCI-STP context(defined by compile flag: HCI_STP_TX) */
+    #if (HCI_STP_TX_TASKLET_LOCK == HCI_STP_TX_TASKLET_RWLOCK)
+        write_lock_bh(&hci_stp_txqlock);
+    #elif (HCI_STP_TX_TASKLET_LOCK == HCI_STP_TX_TASKLET_SPINLOCK)
+        spin_lock_bh(&hci_stp_txqlock);
+    #else
+    #error "HCI_STP_TX_TASKLET_LOCK"
+    #endif
+    }
+}
+
+void hci_stp_txq_unlock (unsigned int ctx)
+{
+    if (ctx == HCI_STP_TXQ_IN_BLZ) {
+        /* lock txq in BlueZ tx tasklet context with hci_stp_tx */
+    #if (HCI_STP_TX_TASKLET_LOCK == HCI_STP_TX_TASKLET_RWLOCK)
+        write_unlock_bh(&hci_stp_txqlock);
+    #elif (HCI_STP_TX_TASKLET_LOCK == HCI_STP_TX_TASKLET_SPINLOCK)
+        spin_unlock_bh(&hci_stp_txqlock);
+    #else
+    #error "HCI_STP_TX_TASKLET_LOCK"
+    #endif
+    }
+    else {
+        /* lock txq in HCI-STP context(defined by compile flag: HCI_STP_TX) */
+    #if (HCI_STP_TX_TASKLET_LOCK == HCI_STP_TX_TASKLET_RWLOCK)
+        write_unlock_bh(&hci_stp_txqlock);
+    #elif (HCI_STP_TX_TASKLET_LOCK == HCI_STP_TX_TASKLET_SPINLOCK)
+        spin_unlock_bh(&hci_stp_txqlock);
+    #else
+    #error "HCI_STP_TX_TASKLET_LOCK"
+    #endif
+    }
+}
+
+void hci_stp_tx_kick (void)
+{
+    tasklet_schedule(&hci_tx_tasklet);
+}
+
+static void hci_stp_tx_tasklet_func(unsigned long data) {
+
+    struct hci_stp *hu = (struct hci_stp *)data;
+
+    /* sanity check to see if status is still correct? */
+    if (unlikely(hdev == NULL)) {
+        BT_ERR_FUNC("Null hdev!\n");
+        BUG_ON(hdev == NULL);
+        return;
+    }
+
+    if (unlikely(hu != hdev->driver_data)) {
+        BT_ERR_FUNC("hu(0x%p) != hdev->driver_data(0x%p)\n",
+            hu, hdev->driver_data);
+        BUG_ON(hu != hdev->driver_data);
+        return;
+    }
+
+    //read_lock(&hci_stp_txq_lock);
+    hci_stp_txq_lock(HCI_STP_TXQ_IN_HCISTP);
+
+    hci_stp_tx_wakeup(hu);
+
+    //read_unlock(&hci_stp_txq_lock);
+    hci_stp_txq_unlock(HCI_STP_TXQ_IN_HCISTP);
+}
+
+/* George: HCI_STP_SENDING and HCI_STP_TX_WAKEUP flags in this function seem
+* to be redundant.
+*/
+static int hci_stp_tx_wakeup(struct hci_stp *hu)
+{
+//    struct hci_dev *hdev = hu->hdev;
+    struct sk_buff *skb;
+    int j = 0;
+
+    BT_TRC_FUNC();
+
+    if (test_and_set_bit(HCI_STP_SENDING, &hu->tx_state)) {
+        set_bit(HCI_STP_TX_WAKEUP, &hu->tx_state);
+        printk("[BT] enqueue and return\n");
+        return 0;
+    }
+
+    BT_DBG_FUNC("hci_stp_tx_wakeup %d\n", __LINE__);
+
+restart:
+    clear_bit(HCI_STP_TX_WAKEUP, &hu->tx_state);
+
+    while ((skb = skb_dequeue(&hu->txq))) {
+        int len;
+        BT_DBG_FUNC("dqueue times = %d\n", ++j);
+
+        /* hci reset cmd check */
+#if HCI_STP_SAFE_RESET
+        if (unlikely(skb->len == ARRAY_SIZE(bt_reset))) {
+            if (unlikely(!memcmp(bt_reset, skb->data, ARRAY_SIZE(bt_reset)))) {
+                atomic_inc(&hu->reset_count);
+                BT_DBG_FUNC("hci reset cmd,f(%d),c(%d)\n",
+                    BT_GET_HDEV_RST_FG(hdev),
+                    atomic_read(&hu->reset_count));
+            }
+        }
+#endif
+
+        if ((len = mtk_wcn_stp_send_data(skb->data, skb->len, BT_TASK_INDX)) == 0 ) {
+            /* can not send */
+            BT_ERR_FUNC("mtk_wcn_stp_send_data can not send\n");
+            BT_ERR_FUNC("Error %s %d\n", __FUNCTION__, __LINE__);
+
+            skb_queue_head(&hu->txq, skb);//Put back to queue head
+            goto END;
+        }
+
+        //hdev->stat.byte_tx += len; // moved into hci_stp_tx_skb_comp()
+        //hci_stp_tx_skb_comp(hu, bt_cb(skb)->pkt_type);
+        hci_stp_tx_skb_comp(hu, skb);
+        kfree_skb(skb);
+    }
+
+END:
+    if (test_bit(HCI_STP_TX_WAKEUP, &hu->tx_state))
+          goto restart;
+
+    clear_bit(HCI_STP_SENDING, &hu->tx_state);
+
+    return 0;
+}
+
+
+#elif (HCI_STP_TX == HCI_STP_TX_THRD)
+
+void hci_stp_tx_init (struct hci_stp *hu)
+{
+    spin_lock_init(&hci_stp_txqlock);
+    init_waitqueue_head(&hci_stp_tx_thrd_wq);
+
+    hci_stp_tx_thrd = kthread_create(hci_stp_tx_thrd_func, (void *)hu, "hci_stpd");
+    if (NULL == hci_stp_tx_thrd) {
+        BT_ERR_FUNC("kthread_create hci_stpd fail!\n");
+    }
+    wake_up_process(hci_stp_tx_thrd);
+
+    return;
+}
+
+void hci_stp_tx_deinit (struct hci_stp *hu)
+{
+    kthread_stop(hci_stp_tx_thrd);
+    hci_stp_tx_thrd = NULL;
+
+    return;
+}
+
+void hci_stp_txq_lock (unsigned int ctx)
+{
+    if (ctx == HCI_STP_TXQ_IN_BLZ) {
+        /* lock txq in BlueZ tx tasklet context */
+        spin_lock(&hci_stp_txqlock);
+    }
+    else {
+        /* lock txq in HCI-STP context(defined by compile flag: HCI_STP_TX) */
+        spin_lock_bh(&hci_stp_txqlock);
+    }
+}
+
+void hci_stp_txq_unlock (unsigned int ctx)
+{
+    if (ctx == HCI_STP_TXQ_IN_BLZ) {
+        spin_unlock(&hci_stp_txqlock);
+    }
+    else {
+        /* lock txq in HCI-STP context(defined by compile flag: HCI_STP_TX) */
+        spin_unlock_bh(&hci_stp_txqlock);
+    }
+}
+
+static int
+hci_stp_tx_thrd_func (void *pdata)
+{
+    struct hci_stp *hu;
+    struct hci_dev *hdev;
+    struct sk_buff *skb;
+    int len;
+
+    hu = (struct hci_stp *)pdata;
+    hdev = hu->hdev;
+
+    /* sanity check to see if status is still correct? */
+    if (unlikely(hdev == NULL)) {
+        BT_ERR_FUNC("Null hdev!\n");
+        BUG_ON(hdev == NULL);
+        return -1;
+    }
+
+    if (unlikely(hu != hdev->driver_data)) {
+        BT_ERR_FUNC("hu(0x%p) != hdev->driver_data(0x%p)\n",
+            hu, hdev->driver_data);
+        BUG_ON(hu != hdev->driver_data);
+        return -1;
+    }
+
+    for (;;) {
+        smp_rmb(); /* sync shared data */
+
+        wait_event_interruptible(hci_stp_tx_thrd_wq,
+            (!skb_queue_empty(&hu->txq) || kthread_should_stop()));
+
+        if (unlikely(kthread_should_stop())) {
+            BT_DBG_FUNC("hci_stpd thread should stop now... \n");
+            break;
+        }
+
+        hci_stp_txq_lock(HCI_STP_TXQ_IN_HCISTP);
+        while ((skb = skb_dequeue(&hu->txq))) {
+            /* protect txq only */
+            hci_stp_txq_unlock(HCI_STP_TXQ_IN_HCISTP);
+
+            /* hci reset cmd check */
+    #if HCI_STP_SAFE_RESET
+            if (unlikely(skb->len == ARRAY_SIZE(bt_reset))) {
+                if (unlikely(!memcmp(bt_reset, skb->data, ARRAY_SIZE(bt_reset)))) {
+                    atomic_inc(&hu->reset_count);
+                    BT_DBG_FUNC("hci reset cmd,f(%d),c(%d)\n",
+                        BT_GET_HDEV_RST_FG(hdev),
+                        atomic_read(&hu->reset_count));
+                }
+            }
+    #endif
+
+            len = mtk_wcn_stp_send_data(skb->data, skb->len, BT_TASK_INDX);
+            if (unlikely(len != skb->len)) {
+                /* can not send */
+                BT_ERR_FUNC("mtk_wcn_stp_send_data fail, enqueue again!(%d, %d)\n",
+                    len, skb->len);
+
+                hci_stp_txq_lock(HCI_STP_TXQ_IN_HCISTP);
+                skb_queue_head(&hu->txq, skb);//Put back to queue head
+                /* do hci_stp_txq_unlock outside while loop */
+                break;
+            }
+            //hdev->stat.byte_tx += len; // moved into hci_stp_tx_skb_comp()
+            hci_stp_tx_skb_comp(hu, skb);
+            kfree_skb(skb);
+
+            hci_stp_txq_lock(HCI_STP_TXQ_IN_HCISTP);
+        }
+        hci_stp_txq_unlock(HCI_STP_TXQ_IN_HCISTP);
+
+        /* back to wait */
+    }
+
+    BT_INFO_FUNC("tx thread stop!\n");
+    return 0;
+}
+
+void hci_stp_tx_kick (void)
+{
+    smp_wmb();
+    wake_up_interruptible(&hci_stp_tx_thrd_wq);
+}
+
+#else
+#error "Not implemented HCI_STP_TX"
+#endif
+
+
+void hci_stp_dev_init_rx_cb (const UINT8 *data, INT32 count)
+{
+    struct hci_stp *hu;
+    unsigned int idx;
+
+    if (unlikely(!hdev)) {
+        BT_ERR_FUNC("null hdev!\n");
+        return;
+    }
+    if (unlikely(!hdev->driver_data)) {
+        BT_ERR_FUNC("null hdev->driver_data!\n");
+        return;
+    }
+
+    /* get hci_stp from global variable */
+    hu = (struct hci_stp *)hdev->driver_data;
+    idx = hu->init_cmd_idx;
+
+    if (unlikely(count != init_table[idx].evtSz)){
+        hu->init_evt_rx_flag = -1; /* size mismatch */
+    }
+    else if (unlikely(memcmp(data, init_table[idx].hci_evt, 7))){
+        hu->init_evt_rx_flag = -2; /* content mismatch */
+    }
+    else{
+        hu->init_evt_rx_flag = 1; /* ok */
+        BT_DBG_FUNC("EVT(%d) len(%d) ok\n", idx, count);
+        if (idx == 0) {
+            /* store the returned eFUSE address */
+            memcpy(&bt_get_bd_addr_evt[7], &data[7], 6);
+        }
+    }
+
+    if (unlikely(1 != hu->init_evt_rx_flag)) {
+        int i;
+        BT_WARN_FUNC("EVT(%d) len(%d) buf:[", idx, count);
+        for (i = 0; i < count; ++i) {
+            printk("0x%02x ", data[i]);
+        }
+        printk("]\n");
+        BT_WARN_FUNC("EVT(%d) exp(%d) buf:[", idx, init_table[idx].evtSz);
+        for (i = 0; i < count; ++i) {
+            printk("0x%02x ", init_table[idx].hci_evt[i]);
+        }
+        printk("]\n");
+
+    }
+
+    smp_wmb(); /* sync shared data */
+
+    spin_lock(&hu->init_lock);
+    if (likely(hu->p_init_evt_wq)) {
+        wake_up(hu->p_init_evt_wq); /* wake up dev_init_work */
+    }
+    else {
+        int i;
+        BT_WARN_FUNC("late EVT(%d) len(%d) buf:[", idx, count);
+        for (i = 0; i < count; ++i) {
+            printk("0x%02x ", data[i]);
+        }
+        printk("]\n");
+        BT_WARN_FUNC("Please check if uart rx data is returned or processed in time for BT init!\n");
+        BT_WARN_FUNC("Possibly caused by a very busy system, or stp_uart rx priority too low...\n");
+        BT_WARN_FUNC("Check which one is the real case and try to raise stp_uart rx priority.\n");
+    }
+    spin_unlock(&hu->init_lock);
+}
+
+static void hci_stp_dev_init_work (struct work_struct *work)
+{
+    struct hci_stp *phu;
+    unsigned int idx;
+    long ret, to;
+
+    struct btradio_conf_data cfg = {
+        {0x00, 0x00, 0x46, 0x66, 0x20, 0x01},
+        {0x60, 0x00},
+        {0x23, 0x10, 0x00, 0x00},
+        {0x06, 0x80, 0x00, 0x06, 0x03, 0x06},
+        {0x03, 0x40, 0x1F, 0x40, 0x1F, 0x00, 0x04},
+        {0x80, 0x00},
+        {0xFF, 0xFF, 0xFF}};
+
+    /* get client's information */
+    phu = container_of(work, struct hci_stp, init_work);
+
+    if (load_custom_bt_conf(&cfg) < 0){
+        BT_INFO_FUNC("No custom BT config\n");
+
+        if (load_internal_bt_conf(&cfg) < 0){
+            BT_ERR_FUNC("Load internal BT config failed!\n");
+        }
+        else{
+            BT_INFO_FUNC("Load internal BT config success\n");
+
+            if (0 == memcmp(cfg.addr, sDefaultCfg.addr, 6)){
+                /* BD address default value, want to retrieve module eFUSE */
+                fgetEFUSE = true;
+                /* retrieve eFUSE address in init command loop */
+            }
+        }
+    }
+    else{
+        BT_INFO_FUNC("Load custom BT config success\n");
+    }
+
+    BT_DBG_FUNC("Read BT config data:\n");
+    BT_DBG_FUNC("[BD address %02x-%02x-%02x-%02x-%02x-%02x]\n",
+        cfg.addr[0], cfg.addr[1], cfg.addr[2], cfg.addr[3], cfg.addr[4], cfg.addr[5]);
+    BT_DBG_FUNC("[voice %02x %02x][codec %02x %02x %02x %02x]\n",
+        cfg.voice[0], cfg.voice[1], cfg.codec[0], cfg.codec[1], cfg.codec[2], cfg.codec[3]);
+    BT_DBG_FUNC("[radio %02x %02x %02x %02x %02x %02x]\n",
+        cfg.radio[0], cfg.radio[1], cfg.radio[2], cfg.radio[3], cfg.radio[4], cfg.radio[5]);
+    BT_DBG_FUNC("[sleep %02x %02x %02x %02x %02x %02x %02x]\n",
+        cfg.sleep[0], cfg.sleep[1], cfg.sleep[2], cfg.sleep[3], cfg.sleep[4], cfg.sleep[5], cfg.sleep[6]);
+    BT_DBG_FUNC("[feature %02x %02x]\n",
+        cfg.feature[0], cfg.feature[1]);
+    BT_DBG_FUNC("[tx power offset %02x %02x %02x]\n",
+        cfg.tx_pwr_offset[0], cfg.tx_pwr_offset[1], cfg.tx_pwr_offset[2]);
+
+    bt_set_bd_addr[4] = cfg.addr[5];
+    bt_set_bd_addr[5] = cfg.addr[4];
+    bt_set_bd_addr[6] = cfg.addr[3];
+    bt_set_bd_addr[7] = cfg.addr[2];
+    bt_set_bd_addr[8] = cfg.addr[1];
+    bt_set_bd_addr[9] = cfg.addr[0];
+
+    memcpy(&bt_set_voice[4], cfg.voice, 2);
+    memcpy(&bt_set_codec[4], cfg.codec, 4);
+    memcpy(&bt_set_radio[4], cfg.radio, 6);
+    memcpy(&bt_set_tx_pwr_offset[4], cfg.tx_pwr_offset, 3);
+    memcpy(&bt_set_sleep[4], cfg.sleep, 7);
+    memcpy(&bt_set_feature[4], cfg.feature, 2);
+
+    /*
+     * INIT command loop starts
+     */
+    if (fgetEFUSE == true)
+        idx = 0;
+    else // skip bt_get_bd_addr
+        idx = 1;
+
+    for (; idx < ARRAY_SIZE(init_table); ++idx) {
+        phu->init_cmd_idx = idx;
+        phu->init_evt_rx_flag = 0;
+        to = (init_table[idx].hci_cmd == bt_reset) ? BT_CMD_DELAY_MS_RESET : BT_CMD_DELAY_MS_COMM;
+        /* safe waiting time in case running on a busy system */
+        to = msecs_to_jiffies(to * BT_CMD_DELAY_SAFE_GUARD);
+
+        BT_DBG_FUNC("CMD(%d) (%s) t/o(%ld))\n", idx, init_table[idx].str, to);
+        smp_wmb(); /* sync shared data */
+
+        /* Send hci command */
+        mtk_wcn_stp_send_data(init_table[idx].hci_cmd, init_table[idx].cmdSz, BT_TASK_INDX);
+        /* Wait rx hci event */
+        /* no need to lock init_lock here for wq, for that it will be freed
+         * only after we call complete(phu->p_init_comp); in this function.
+         */
+        ret = wait_event_timeout((*phu->p_init_evt_wq), phu->init_evt_rx_flag != 0, to);
+
+        /* Check result */
+        if (likely(1 == phu->init_evt_rx_flag)) {
+            if (idx == 0) 
+            { // bt_get_bd_addr event handler
+                unsigned long randNum;
+                loff_t pos = 0;
+                ssize_t written;
+
+                BT_DBG_FUNC("Retrieve eFUSE address %02x-%02x-%02x-%02x-%02x-%02x\n",
+                    bt_get_bd_addr_evt[12], bt_get_bd_addr_evt[11], bt_get_bd_addr_evt[10], bt_get_bd_addr_evt[9], bt_get_bd_addr_evt[8], bt_get_bd_addr_evt[7]);
+
+                cfg.addr[0] = bt_get_bd_addr_evt[12];
+                cfg.addr[1] = bt_get_bd_addr_evt[11];
+                cfg.addr[2] = bt_get_bd_addr_evt[10];
+                cfg.addr[3] = bt_get_bd_addr_evt[9];
+                cfg.addr[4] = bt_get_bd_addr_evt[8];
+                cfg.addr[5] = bt_get_bd_addr_evt[7];
+
+                if (0 == memcmp(cfg.addr, sDefaultCfg.addr, 6)){
+                #if BD_ADDR_AUTOGEN
+                    /* eFUSE address default value, enable auto-gen */
+                    BT_DBG_FUNC("eFUSE address default value, enable auto-gen!\n");
+                    get_random_bytes(&randNum, sizeof(unsigned long));
+                    BT_DBG_FUNC("Get random number: %lu\n", randNum);
+
+                    bt_get_bd_addr_evt[12] = (((randNum>>24 | randNum>>16) & (0xFE)) | (0x02));
+                    bt_get_bd_addr_evt[11] = ((randNum>>8) & 0xFF);
+                    bt_get_bd_addr_evt[7] = (randNum & 0xFF);
+                    
+                    cfg.addr[0] = bt_get_bd_addr_evt[12];
+                    cfg.addr[1] = bt_get_bd_addr_evt[11];
+                    cfg.addr[5] = bt_get_bd_addr_evt[7];
+                #endif
+                }
+                else {
+                    /* eFUSE address has valid value */
+                }
+
+                memcpy(&bt_set_bd_addr[4], &bt_get_bd_addr_evt[7], 6);
+
+                /* Update BD address in internal BT config file */
+                pos = 0;
+                written = file_write(INTERNAL_BT_CFG_FILE,
+                                     (char*)&cfg,
+                                     6,
+                                     &pos);
+
+                /* Clear flag */
+                fgetEFUSE = false;
+            }
+            /* Process next cmd */
+            continue;
+        }
+        else {
+            BT_ERR_FUNC("EVT(%d) ret(%u) rx_flag(%d)<=\n",
+                idx, jiffies_to_msecs(ret), phu->init_evt_rx_flag);
+            /* Stop processing and skip next cmd */
+            break;
+        }
+    }
+
+    if (phu->p_init_comp) {
+        complete(phu->p_init_comp);
+    }
+}
+
+static int hci_stp_dev_init (struct hci_stp *phu)
+{
+    DECLARE_COMPLETION_ONSTACK(hci_stp_dev_init_comp);
+    DECLARE_WAIT_QUEUE_HEAD_ONSTACK(hci_stp_dev_init_wq);
+
+    spin_lock(&phu->init_lock);
+    phu->p_init_comp = &hci_stp_dev_init_comp;
+    phu->p_init_evt_wq = &hci_stp_dev_init_wq;
+    spin_unlock(&phu->init_lock);
+
+    /* unregister rx event callback */
+    mtk_wcn_stp_register_event_cb(BT_TASK_INDX, NULL);
+    /* register direct rx callback for init only */
+    mtk_wcn_stp_register_if_rx(hci_stp_dev_init_rx_cb);
+    /* use bluez mode */
+    mtk_wcn_stp_set_bluez(1);
+
+    /* Schedule to call hci_stp_dev_init_work(). init_work is initialized in
+     * hci_stp_init().
+     */
+    schedule_work(&phu->init_work);
+
+    wait_for_completion(&hci_stp_dev_init_comp);
+
+    spin_lock(&phu->init_lock);
+    /* clear references to stack variables */
+    phu->p_init_comp = NULL;
+    phu->p_init_evt_wq = NULL;
+    spin_unlock(&phu->init_lock);
+
+    /* check result */
+    /* flag: (to be replaced by a constant value)
+        1 rx event correctly,
+        0 no response in time,
+        -1 unequal rx event length,
+        -2 unequal rx event content.
+    */
+    if (likely(1 == phu->init_evt_rx_flag)) {
+        return 0;
+    }
+    else {
+        /* return non-zero value for error */
+        return (phu->init_evt_rx_flag + 256);
+    }
+}
+
+/* Invoked when there is ONE received BT packet */
+void stp_tx_event_cb(void)
+{
+#if 0
+    struct hci_stp *hu;
+    if (unlikely(hdev == NULL)) {
+        BT_ERR_FUNC("Null hdev!\n");
+        BUG_ON(hdev == NULL);
+        return;
+    }
+    hu = (struct hci_stp *) hdev->driver_data;
+#endif
+    /* George: [FixMe] can we call hci_stp_tx_wakeup() directly in STP-CORE's
+     * context? It seems to be dangerous! Replace it with suitable one according
+     * to HCI_STP_TX compile flag.
+     */
+    hci_stp_tx_kick(); /* George: adapt different tx_kick function */
+}
+
+/*
+  Direct delivery of bluez not changed hands through the stp buffer
+*/
+void stp_rx_event_cb_directly(const UINT8 *data, INT32 count)
+{
+    register const UINT8 *ptr;
+    struct hci_event_hdr *eh;
+    struct hci_acl_hdr   *ah;
+    struct hci_sco_hdr   *sh;
+    register int len, type, dlen;
+    int while_count; /* = 0; Is while_count redundant? */
+    //static unsigned long rx_count; /* Is it ok w/o an initial value??? */
+    static unsigned int rx_count = 0;
+    //static unsigned long rx_state; /* Is it ok w/o an initial value??? */
+    static unsigned int rx_state = H4_W4_PACKET_TYPE;
+    struct  sk_buff *rx_skb = NULL; /* Is it ok to use non-static skb??? */
+    register int room;
+#if HCI_STP_SAFE_RESET
+    struct hci_stp *hu;
+#endif
+
+    BT_LOUD_FUNC("count(%d)rx_state(%d)rx_count(%d)\n",
+        count, rx_state, rx_count);
+
+    if (data == NULL) {
+        BT_ERR_FUNC("Data is Null\n");
+        return;
+    }
+
+    if (count > 5000) {
+        BT_WARN_FUNC("abnormal count(%d)\n", count);
+    }
+
+    ptr = data;
+    /*Add statistic*/
+    hdev->stat.byte_rx += count;
+
+#if HCI_STP_SAFE_RESET
+    hu = (struct hci_stp *)hdev->driver_data;
+    /* is waiting hci reset event? */
+    if (unlikely(atomic_read(&hu->reset_count))) {
+        if (count == ARRAY_SIZE(bt_reset_evt)) {
+            if (!memcmp(bt_reset_evt, data, ARRAY_SIZE(bt_reset_evt))) {
+                BT_DBG_FUNC("hci reset evt,f(%d),c(%d)\n",
+                    BT_GET_HDEV_RST_FG(hdev),
+                    atomic_read(&hu->reset_count));
+
+                atomic_dec(&hu->reset_count);
+                wake_up(&hu->reset_wq);
+            }
+        }
+    }
+#endif
+
+    while_count = 0;
+    while (count > 0) { /* while (count) */
+        /* Is while_count redundant? */
+        //while_count++;
+        if (++while_count > 5000) {
+            BT_WARN_FUNC("abnormal while_count(%d)\n", while_count);
+        }
+
+        if (rx_count) {
+            len = min_t(unsigned int, rx_count, count);
+            memcpy(skb_put(rx_skb, len), ptr, len);
+            rx_count -= len;
+            count -= len;
+            ptr += len;
+
+            if (rx_count)
+                continue;
+            /* rx_count==0, ready to indicate to hci_core */
+
+            switch (rx_state) {
+            case H4_W4_DATA:
+                BT_LOUD_FUNC("Complete data\n");
+                hci_recv_frame(rx_skb);
+                rx_state = H4_W4_PACKET_TYPE;
+                rx_skb = NULL;
+                continue;
+
+            case H4_W4_EVENT_HDR:
+                eh = hci_event_hdr(rx_skb);
+                //BT_DBG_FUNC("Event header:evt(0x%2.2x)plen(%d)\n", eh->evt, eh->plen);
+                room = skb_tailroom(rx_skb);
+                //BT_DBG_FUNC("len(%d)room(%d)\n", eh->plen, room);
+                BT_LOUD_FUNC("Event header:evt(0x%2.2x)plen(%d)room(%d)\n",
+                    eh->evt, eh->plen, room);
+
+                if (!eh->plen) {
+                    hci_recv_frame(rx_skb);
+                    rx_state = H4_W4_PACKET_TYPE;
+                    rx_skb   = NULL;
+                    rx_count = 0; /* redundant? here rx_count is 0 already */
+                }
+                else if (eh->plen > room) {
+                    //BT_ERR("Data length is too large\n");
+                    BT_ERR_FUNC("too large data length:eh->plen(%d)>room(%d)\n",
+                        eh->plen, room);
+                    kfree_skb(rx_skb);
+                    rx_state = H4_W4_PACKET_TYPE;
+                    rx_skb = NULL;
+                    rx_count = 0; /* redundant? here rx_count is 0 already */
+                }
+                else {
+                    rx_state = H4_W4_DATA;
+                    rx_count = eh->plen;
+                }
+                continue;
+
+            case H4_W4_ACL_HDR:
+                ah = hci_acl_hdr(rx_skb);
+                dlen = __le16_to_cpu(ah->dlen);
+
+                room = skb_tailroom(rx_skb);
+                BT_LOUD_FUNC("ACL header:dlen(%d)room(%d)\n", dlen, room);
+                if (!dlen) {
+                    hci_recv_frame(rx_skb);
+                    rx_state = H4_W4_PACKET_TYPE;
+                    rx_skb = NULL;
+                    rx_count = 0;
+                }
+                else if (dlen > room) {
+                    //BT_ERR_FUNC("Data length is too large\n");
+                    BT_ERR_FUNC("too large data length:dlen(%d)>room(%d)\n",
+                        dlen, room);
+                    kfree_skb(rx_skb);
+                    rx_state = H4_W4_PACKET_TYPE;
+                    rx_skb = NULL;
+                    rx_count = 0;
+                }
+                else {
+                    rx_state = H4_W4_DATA;
+                    rx_count = dlen;
+                }
+                continue;
+
+            case H4_W4_SCO_HDR:
+                sh = hci_sco_hdr(rx_skb);
+                room = skb_tailroom(rx_skb);
+                BT_LOUD_FUNC("SCO header:dlen(%d)room(%d)\n", sh->dlen, room);
+
+                if (!sh->dlen) {
+                    hci_recv_frame(rx_skb);
+                    rx_state = H4_W4_PACKET_TYPE;
+                    rx_skb = NULL;
+                    rx_count = 0;
+                }
+                else if (sh->dlen > room) {
+                    BT_ERR_FUNC("Data length is too large\n");
+                    BT_ERR_FUNC("too large data length:sh->dlen(%d)>room(%d)\n",
+                        sh->dlen , room);
+                    kfree_skb(rx_skb);
+                    rx_state = H4_W4_PACKET_TYPE;
+                    rx_skb = NULL;
+                    rx_count = 0;
+                }
+                else {
+                    rx_state = H4_W4_DATA;
+                    rx_count = sh->dlen;
+                }
+                continue;
+            }
+        }
+
+        /* H4_W4_PACKET_TYPE */
+        switch (*ptr) {
+            case HCI_EVENT_PKT:
+                BT_LOUD_FUNC("Event packet\n");
+                rx_state = H4_W4_EVENT_HDR;
+                rx_count = HCI_EVENT_HDR_SIZE;
+                type = HCI_EVENT_PKT;
+                break;
+
+            case HCI_ACLDATA_PKT:
+                BT_LOUD_FUNC("ACL packet\n");
+                rx_state = H4_W4_ACL_HDR;
+                rx_count = HCI_ACL_HDR_SIZE;
+                type = HCI_ACLDATA_PKT;
+                break;
+
+            case HCI_SCODATA_PKT:
+                BT_LOUD_FUNC("SCO packet\n");
+                rx_state = H4_W4_SCO_HDR;
+                rx_count = HCI_SCO_HDR_SIZE;
+                type = HCI_SCODATA_PKT;
+                break;
+
+            default:
+                BT_ERR_FUNC("Unknown HCI packet type %2.2x\n", (__u8)*ptr);
+                ++(hdev->stat.err_rx);
+                ++ptr;
+                --count;
+                continue;
+        };
+
+        ++ptr;
+        --count;
+
+        /* Allocate packet */
+        rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
+        if (!rx_skb) {
+           BT_ERR_FUNC("bt_skb_alloc(%d, GFP_ATOMIC) fail!\n", HCI_MAX_FRAME_SIZE);
+           rx_state = H4_W4_PACKET_TYPE;
+           rx_count = 0;
+           return;
+        }
+
+        rx_skb->dev = (void *) hdev;
+        bt_cb(rx_skb)->pkt_type = type;
+    }
+
+    return;
+}
+
+/* ------- Interface to HCI layer ------ */
+/* Initialize device */
+static int hci_stp_open(struct hci_dev *hdev)
+{
+    struct hci_stp *hu;
+    int ret;
+
+    if (unlikely(!hdev)) {
+        BT_ERR_FUNC("null hdev\n");
+        return -ENODEV;
+    }
+
+    if (unlikely(!hdev->driver_data)) {
+        BT_ERR_FUNC("null hdev\n");
+        return -ENODEV;
+    }
+
+    hu = (struct hci_stp *)hdev->driver_data;
+    BT_INFO_FUNC("%s(0x%p)\n", hdev->name, hdev);
+
+    /* clear txq and free all skb in it */
+    hci_stp_txq_lock(HCI_STP_TXQ_IN_BLZ);
+    skb_queue_purge(&hu->txq);
+    hci_stp_txq_unlock(HCI_STP_TXQ_IN_BLZ);
+
+    /* turn on BT */
+    if (unlikely(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");
+
+    if (likely(mtk_wcn_stp_is_ready())) {
+        BT_DBG_FUNC("STP is ready!\n");
+
+        ret = hci_stp_dev_init(hu);
+        /* error handling: turn off BT */
+        if (unlikely(ret)) {
+            BT_WARN_FUNC("hci_stp_dev_init fail(%d)!\n", ret);
+            if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_off(WMTDRV_TYPE_BT)) {
+                BT_WARN_FUNC("WMT turn off BT fail!\n");
+            }
+            else {
+                BT_INFO_FUNC("WMT turn off BT ok!\n");
+            }
+            return -ENODEV;
+        }
+
+        BT_INFO_FUNC("hci_stp_dev_init ok\n");
+
+        set_bit(HCI_RUNNING, &hdev->flags);
+
+        /* registered tx/rx path */
+        mtk_wcn_stp_register_if_rx(stp_rx_event_cb_directly);
+
+        mtk_wcn_stp_register_event_cb(BT_TASK_INDX, NULL);
+        mtk_wcn_stp_register_tx_event_cb(BT_TASK_INDX, stp_tx_event_cb);
+
+        /* use bluez */
+        mtk_wcn_stp_set_bluez(1);
+
+        return 0;
+    }
+    else {
+        BT_WARN_FUNC("STP is not ready!\n");
+        return -ENODEV;
+    }
+}
+
+/* Reset device */
+static int hci_stp_flush(struct hci_dev *hdev)
+{
+    struct hci_stp *hu;
+
+    BT_DBG_FUNC("start\n");
+    if (!hdev || !hdev->driver_data) {
+        BT_WARN_FUNC("invalid hdev(0x%p) or drv data(0x%p)\n",
+            hdev, (hdev) ? hdev->driver_data : hdev);
+        return -EFAULT;
+    }
+
+    hu = (struct hci_stp *)hdev->driver_data;
+
+    /* clear txq and free all skb in it */
+    hci_stp_txq_lock(HCI_STP_TXQ_IN_BLZ);
+    skb_queue_purge(&hu->txq);
+    hci_stp_txq_unlock(HCI_STP_TXQ_IN_BLZ);
+
+    BT_INFO_FUNC("done\n");
+    return 0;
+}
+
+/* Close device */
+static int hci_stp_close(struct hci_dev *hdev)
+{
+#if HCI_STP_SAFE_RESET
+    struct hci_stp *hu;
+    long ret;
+#endif
+
+    BT_INFO_FUNC("hdev(0x%p)\n", hdev);
+
+    if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags)) {
+          return 0;
+    }
+
+    hci_stp_flush(hdev);
+    hdev->flush = NULL;
+
+#if HCI_STP_SAFE_RESET
+    hu = (struct hci_stp *)hdev->driver_data;
+    if (hu) {
+        /* double waiting time in case of busy system */
+        ret = wait_event_timeout((hu->reset_wq),
+            (atomic_read(&hu->reset_count) == 0),
+            msecs_to_jiffies(BT_CMD_DELAY_MS_RESET*2));
+        if ( (!ret) || (atomic_read(&hu->reset_count) != 0) ) {
+            BT_WARN_FUNC("wait on-going reset finish fail,f(%d),c(%d),ret(%u)\n",
+                BT_GET_HDEV_RST_FG(hdev),
+                atomic_read(&hu->reset_count),
+                jiffies_to_msecs(ret));
+        }
+        else {
+            BT_DBG_FUNC("check reset log,f(%d),c(%d),ret(%u)\n",
+                BT_GET_HDEV_RST_FG(hdev),
+                atomic_read(&hu->reset_count),
+                jiffies_to_msecs(ret));
+        }
+    }
+#endif
+
+    /* clear txq and free all skb in it */
+    hci_stp_txq_lock(HCI_STP_TXQ_IN_BLZ);
+    skb_queue_purge(&hu->txq);
+    hci_stp_txq_unlock(HCI_STP_TXQ_IN_BLZ);
+
+    /* unregistered tx/rx path */
+    mtk_wcn_stp_register_if_rx(NULL);
+
+    mtk_wcn_stp_register_event_cb(BT_TASK_INDX, NULL);
+    mtk_wcn_stp_register_tx_event_cb(BT_TASK_INDX, NULL);
+
+    /* not use bluez */
+    mtk_wcn_stp_set_bluez(0);
+
+    if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_off(WMTDRV_TYPE_BT)) {
+        BT_WARN_FUNC("WMT turn off BT fail!\n");
+    }
+    else {
+        BT_INFO_FUNC("WMT turn off BT OK!\n");
+    }
+
+    return 0;
+}
+
+/* Send frames from HCI layer */
+static int hci_stp_send_frame(struct sk_buff *skb)
+{
+    struct hci_dev* hdev = (struct hci_dev *) skb->dev;
+    struct hci_stp *hu;
+
+    if (!hdev) {
+        BT_ERR_FUNC("Null hdev in skb\n");
+        return -ENODEV;
+    }
+
+    if (!test_bit(HCI_RUNNING, &hdev->flags)) {
+        BT_ERR_FUNC("no HCI_RUNNING in hdev->flags(0x%lx)\n", hdev->flags);
+        return -EBUSY;
+    }
+
+    hu = (struct hci_stp *) hdev->driver_data;
+
+    BT_LOUD_FUNC("%s: type(%d) len(%d)\n",
+        hdev->name, bt_cb(skb)->pkt_type, skb->len);
+
+#if 0 /* just timestamp?? */
+    if (gDbgLevel >= BT_LOG_DBG)
+    {
+        struct timeval now;
+        do_gettimeofday(&now);
+        printk("%s: sec = %ld, --> usec --> %ld\n",
+             __FUNCTION__, now.tv_sec, now.tv_usec);
+    }
+#endif
+
+    /* Prepend skb with frame type. Is it safe to do skb_push? */
+    memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
+
+    /* George: is no lock ok?? Add hci_stp_txq_lock and unlock! */
+    hci_stp_txq_lock(HCI_STP_TXQ_IN_BLZ);
+    /*Queue a buffer at the end of a list. This function takes no locks
+    *  and you must therefore hold required locks before calling it.
+    */
+    skb_queue_tail(&hu->txq, skb);
+    hci_stp_txq_unlock(HCI_STP_TXQ_IN_BLZ);
+
+    /* George: adapt different tx_kick function */
+    hci_stp_tx_kick();
+
+    return 0;
+}
+
+static void hci_stp_destruct(struct hci_dev *hdev)
+{
+    BT_TRC_FUNC();
+
+    if (!hdev) {
+        return;
+    }
+
+    BT_DBG_FUNC("%s\n", hdev->name);
+    hci_stp_tx_deinit((struct hci_stp *)hdev->driver_data);
+    kfree(hdev->driver_data);
+}
+
+static int __init hci_stp_init(void)
+{
+    struct hci_stp *hu = NULL;
+
+    if (!(hu = kzalloc(sizeof(struct hci_stp), GFP_ATOMIC))) {
+        BT_ERR_FUNC("Can't allocate control structure\n");
+        return -ENOMEM;
+    }
+
+    BT_DBG_FUNC("hu 0x%08x\n", (int)hu);
+
+    /*
+       used to stored pending skb
+     */
+    skb_queue_head_init(&hu->txq);
+
+    /*
+       Initialize and register HCI device
+     */
+    hdev = hci_alloc_dev();
+    if (!hdev) {
+        if (hu){
+            kfree(hu);
+            hu = NULL;
+        }
+
+        BT_ERR_FUNC("Can't allocate HCI device\n");
+        return -ENOMEM;
+    }
+
+    hu->hdev = hdev;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34))
+    hdev->type = HCI_UART;
+#else
+    hdev->bus = HCI_UART;
+    hdev->dev_type = HCI_BREDR;
+#endif
+    hdev->driver_data = hu;
+
+    BT_DBG_FUNC("hdev->driver_data 0x%08x\n", (int)hdev->driver_data);
+    hdev->open  = hci_stp_open;
+    hdev->close = hci_stp_close;
+    hdev->flush = hci_stp_flush;
+    hdev->send  = hci_stp_send_frame;
+    hdev->destruct = hci_stp_destruct;
+
+    hdev->owner = THIS_MODULE;
+
+    BT_DBG_FUNC("HCI_QUIRK_NO_RESET\n");
+
+    set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks);
+
+    if (hci_register_dev(hdev) < 0) {
+        BT_ERR_FUNC("Can't register HCI device\n");
+        kfree(hu);
+        hu = NULL;
+        hci_free_dev(hdev);
+        hdev = NULL;
+        return -ENODEV;
+     }
+
+#if HCI_STP_SAFE_RESET
+    atomic_set(&hu->reset_count, 0);
+    init_waitqueue_head(&hu->reset_wq);
+#endif
+
+    /* George: adapt different tx_init function */
+    hci_stp_tx_init(hu);
+
+    /* init_work in heap */
+    INIT_WORK(&hu->init_work, hci_stp_dev_init_work);
+    spin_lock_init(&hu->init_lock);
+
+    mtk_wcn_stp_register_if_rx(NULL);
+    mtk_wcn_stp_register_event_cb(BT_TASK_INDX, NULL);
+    mtk_wcn_stp_register_tx_event_cb(BT_TASK_INDX, NULL);
+
+    BT_INFO_FUNC("HCI STP driver ver %s, hdev(0x%p), init done\n", VERSION, hdev);
+
+    return 0;
+}
+
+static void __exit hci_stp_exit(void)
+{
+    struct hci_stp *hu = (struct hci_stp *)hdev->driver_data;
+
+    BT_TRC_FUNC();
+
+    mtk_wcn_stp_register_event_cb(BT_TASK_INDX, NULL);
+    mtk_wcn_stp_register_tx_event_cb(BT_TASK_INDX, NULL);
+
+    hci_unregister_dev(hdev);
+
+    /* George: adapt different tx_deinit function */
+    //tasklet_kill(&hci_tx_tasklet);
+
+    skb_queue_purge(&hu->txq);
+
+    /* hci_stp_destruct does this */
+    /*kfree(hdev->driver_data);*/
+    hci_free_dev(hdev);
+
+    hdev = NULL;
+}
+
+module_init(hci_stp_init);
+module_exit(hci_stp_exit);
+
+module_param(reset, bool, 0644);
+MODULE_PARM_DESC(reset, "Send HCI reset command on initialization");
+
+MODULE_AUTHOR("Mediatek Inc.");
+MODULE_DESCRIPTION("Bluetooth HCI STP driver ver " VERSION);
+MODULE_VERSION(VERSION);
+MODULE_LICENSE("GPL");
+
+
diff --git a/drivers/mtk_wcn_combo/drv_fm/Makefile b/drivers/mtk_wcn_combo/drv_fm/Makefile
new file mode 100755 (executable)
index 0000000..e9fec34
--- /dev/null
@@ -0,0 +1,82 @@
+# Makefile generated by Mediatek
+# fm support
+
+#6628 FM driver
+ifeq ($(CONFIG_MTK_COMBO_CHIP_MT6628), y)
+$(warning MT6628_FM)
+ccflags-y += -I$(src)/inc \
+                        -I$(src)/mt6628/inc \
+                        -I$(src)/../common/include \
+                        -I$(src)/../common/linux/include \
+                        -I$(src)/cust/mt6628 \
+                        -I$(src)/private/inc \
+                        -DMT6628_FM
+
+obj-$(CONFIG_MTK_COMBO_FM) += mtk_fm_drv.o
+       mtk_fm_drv-objs +=  core/fm_module.o \
+                                               core/fm_main.o \
+                                               core/fm_config.o \
+                                               core/fm_rds_parser.o \
+                                               core/fm_patch.o \
+                                               core/fm_utils.o \
+                                               core/fm_link.o \
+                                               core/fm_eint.o  \
+                                               mt6628/pub/mt6628_fm_lib.o \
+                                               mt6628/pub/mt6628_fm_rds.o \
+                                               mt6628/pub/mt6628_fm_cmd.o \
+                                               mt6628/pub/mt6628_fm_config.o
+$(warning $(mtk_fm_drv-objs))
+endif
+
+# MT6620 FM driver
+ifeq ($(CONFIG_MTK_COMBO_CHIP_MT6620), y)
+$(warning MT6620_FM)
+       ccflags-y += -I$(src)/inc \
+                                       -I$(src)/mt6620/inc \
+                                       -I$(src)/../common/include \
+                                       -I$(src)/../common/linux/include \
+                                       -I$(src)/cust/mt6620 \
+                                       -I$(src)/private/inc \
+                                       -DMT6620_FM
+
+       obj-$(CONFIG_MTK_COMBO_FM) += mtk_fm_drv.o
+       mtk_fm_drv-objs += core/fm_module.o \
+                                       core/fm_main.o \
+                                       core/fm_config.o \
+                                       core/fm_rds_parser.o \
+                                       core/fm_patch.o \
+                                       core/fm_utils.o \
+                                       core/fm_link.o \
+                                       core/fm_eint.o \
+                                       mt6620/pub/mt6620_fm_lib.o \
+                                       mt6620/pub/mt6620_fm_rds.o \
+                                       mt6620/pub/mt6620_fm_cmd.o \
+                                       mt6620/pub/mt6620_fm_config.o
+$(warning $(mtk_fm_drv-objs))
+endif
+
+# MT6626 FM driver 
+ifeq ($(CONFIG_MTK_COMBO_CHIP_MT6626), y)
+FM_CHIP = mt6626
+FM_CHIP_PATH = $(FM_CHIP)/pub/$(FM_CHIP)
+ccflags-y := -I$(src)/inc \
+                               -I$(src)/$(FM_CHIP)/inc \
+                               -I$(src)/cust/$(FM_CHIP) \
+                               -I$(src)/private/inc \
+                               -DMT6626_FM
+
+obj-$(CONFIG_MTK_COMBO_FM) += mtk_fm_drv.o
+mtk_fm_drv-objs        := core/fm_module.o \
+                               core/fm_main.o \
+                               core/fm_config.o \
+                               core/fm_patch.o \
+                               core/fm_rds_parser.o \
+                               core/fm_utils.o \
+                               core/fm_link.o \
+                               $(FM_CHIP_PATH)_fm_lib.o \
+                               $(FM_CHIP_PATH)_fm_rds.o \
+                               $(FM_CHIP_PATH)_fm_link.o \
+                               $(FM_CHIP_PATH)_fm_eint.o
+endif
+
+
diff --git a/drivers/mtk_wcn_combo/drv_fm/core/fm_config.c b/drivers/mtk_wcn_combo/drv_fm/core/fm_config.c
new file mode 100755 (executable)
index 0000000..7529ab2
--- /dev/null
@@ -0,0 +1,597 @@
+/* fm_config.c
+ *
+ * (C) Copyright 2011
+ * MediaTek <www.MediaTek.com>
+ * hongcheng <hongcheng.xia@MediaTek.com>
+ *
+ * FM Radio Driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "fm_typedef.h"
+#include "fm_rds.h"
+#include "fm_dbg.h"
+#include "fm_err.h"
+#include "fm_stdlib.h"
+#include "fm_patch.h"
+#include "fm_config.h"
+#if (!defined(MT6628_FM)&&!defined(MT6620_FM))
+#include "fm_cust_cfg.h"
+#endif
+static fm_cust_cfg fm_config;
+static fm_s32 fm_index = 0;
+
+#if 0
+static fm_s32 to_upper(fm_s8 *str)
+{
+    fm_s32 i = 0;
+
+    for (i = 0; i < (int)strlen(str); i++) {
+        if (('a' <= str[i]) && (str[i] <= 'z')) {
+            str[i] = str[i] - ('a' - 'A');
+        }
+    }
+
+    return 0;
+}
+#endif
+
+fm_s32 to_upper_n(fm_s8 *str, fm_s32 len)
+{
+    fm_s32 i = 0;
+
+    for (i = 0; i < len; i++) {
+        if (('a' <= str[i]) && (str[i] <= 'z')) {
+            str[i] = str[i] - ('a' - 'A');
+        }
+    }
+
+    return 0;
+}
+
+fm_s32 check_hex_str(fm_s8 *str, fm_s32 len)
+{
+    fm_s32 i = 0;
+
+    for (i = 0; i < len; i++) {
+        if ((('a' <= str[i]) && (str[i] <= 'z')) || (('A' <= str[i]) && (str[i] <= 'Z')) || (('0' <= str[i]) && (str[i] <= '9'))) {
+            ;
+        } else {
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+fm_s32 check_dec_str(fm_s8 *str, fm_s32 len)
+{
+    fm_s32 i = 0;
+
+    for (i = 0; i < len; i++) {
+        if (('0' <= str[i]) && (str[i] <= '9')) {
+            ;
+        } else {
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+fm_s32 ascii_to_hex(fm_s8 *in_ascii, fm_u16 *out_hex)
+{
+    fm_s32 len = (fm_s32)strlen(in_ascii);
+    int    i = 0;
+    fm_u16 tmp;
+
+    len = (len > 4) ? 4 : len;
+
+    if (check_hex_str(in_ascii, len)) {
+        return -1;
+    }
+
+    to_upper_n(in_ascii, len);
+    *out_hex = 0;
+
+    for (i = 0; i < len; i++) {
+        if (in_ascii[len-i-1] < 'A') {
+            tmp = in_ascii[len-i-1];
+            *out_hex |= ((tmp - '0') << (4 * i));
+        } else {
+            tmp = in_ascii[len-i-1];
+            *out_hex |= ((tmp - 'A' + 10) << (4 * i));
+        }
+    }
+
+    return 0;
+}
+
+fm_s32 ascii_to_dec(fm_s8 *in_ascii, fm_s32 *out_dec)
+{
+    fm_s32 len = (fm_s32)strlen(in_ascii);
+    int i = 0;
+    int flag;
+    int multi = 1;
+
+    len = (len > 10) ? 10 : len;
+
+    if (in_ascii[0] == '-') {
+        flag = -1;
+        in_ascii += 1;
+        len -= 1;
+    } else {
+        flag = 1;
+    }
+
+    if (check_dec_str(in_ascii, len)) {
+        return -1;
+    }
+
+    *out_dec = 0;
+    multi = 1;
+
+    for (i = 0; i < len; i++) {
+        *out_dec += ((in_ascii[len-i-1] - '0') * multi);
+        multi *= 10;
+    }
+
+    *out_dec *= flag;
+    return 0;
+}
+
+fm_s32 trim_string(fm_s8 **start)
+{
+    fm_s8 *end = *start;
+
+    /* Advance to non-space character */
+    while (*(*start) == ' ') {
+        (*start)++;
+    }
+
+    /* Move to end of string */
+    while (*end != '\0') {
+        (end)++;
+    }
+
+    /* Backup to non-space character */
+    do {
+        end--;
+    } while ((end >= *start) && (*end == ' '));
+
+    /* Terminate string after last non-space character */
+    *(++end) = '\0';
+    return (end - *start);
+}
+
+fm_s32 trim_path(fm_s8 **start)
+{
+    fm_s8 *end = *start;
+
+    while (*(*start) == ' ') {
+        (*start)++;
+    }
+
+    while (*end != '\0') {
+        (end)++;
+    }
+
+    do {
+        end--;
+    } while ((end >= *start) && ((*end == ' ') || (*end == '\n') || (*end == '\r')));
+
+    *(++end) = '\0';
+    return (end - *start);
+}
+
+fm_s32 cfg_parser(fm_s8 *buffer, CFG_HANDLER handler, fm_cust_cfg *cfg)
+{
+    fm_s32 ret = 0;
+    fm_s8 *p = buffer;
+    fm_s8 *group_start = NULL;
+    fm_s8 *key_start = NULL;
+    fm_s8 *value_start = NULL;
+
+    enum fm_cfg_parser_state state = FM_CFG_STAT_NONE;
+
+    FMR_ASSERT(p);
+
+    for (p = buffer; *p != '\0'; p++) {
+        switch (state) {
+        case FM_CFG_STAT_NONE: {
+            if (*p == '[') {
+                //if we get char '[' in none state, it means a new group name start
+                state = FM_CFG_STAT_GROUP;
+                group_start = p + 1;
+            } else if (*p == COMMENT_CHAR) {
+                //if we get char '#' in none state, it means a new comment start
+                state = FM_CFG_STAT_COMMENT;
+            } else if (!isspace(*p) && (*p != '\n') && (*p != '\r')) {
+                //if we get an nonspace char in none state, it means a new key start
+                state = FM_CFG_STAT_KEY;
+                key_start = p;
+            }
+
+            break;
+        }
+        case FM_CFG_STAT_GROUP: {
+            if (*p == ']') {
+                //if we get char ']' in group state, it means a group name complete
+                *p = '\0';
+                //FIX_ME
+                //record group name
+                state = FM_CFG_STAT_NONE;
+                trim_string(&group_start);
+                //WCN_DBG(FM_NTC|MAIN, "g=%s\n", group_start);
+            }
+
+            break;
+        }
+        case FM_CFG_STAT_COMMENT: {
+            if (*p == '\n') {
+                //if we get char '\n' in comment state, it means new line start
+                state = FM_CFG_STAT_NONE;
+                group_start = p + 1;
+            }
+
+            break;
+        }
+        case FM_CFG_STAT_KEY: {
+            if (*p == DELIMIT_CHAR) {
+                //if we get char '=' in key state, it means a key name complete
+                *p = '\0';
+                //FIX_ME
+                //record key name
+                state = FM_CFG_STAT_VALUE;
+                value_start = p + 1;
+                trim_string(&key_start);
+                //WCN_DBG(FM_NTC|MAIN, "k=%s\n", key_start);
+            }
+
+            break;
+        }
+        case FM_CFG_STAT_VALUE: {
+            if (*p == '\n' || *p == '\r') {
+                //if we get char '\n' or '\r' in value state, it means a value complete
+                *p = '\0';
+                //record value
+                trim_string(&value_start);
+                //WCN_DBG(FM_NTC|MAIN, "v=%s\n", value_start);
+
+                if (handler) {
+                    ret = handler(group_start, key_start, value_start, cfg);
+                }
+
+                state = FM_CFG_STAT_NONE;
+            }
+
+            break;
+        }
+        default:
+            break;
+        }
+    }
+
+    return ret;
+}
+
+fm_s32 cfg_item_match(fm_s8 *src_key, fm_s8 *src_val, fm_s8 *dst_key, fm_s32 *dst_val)
+{
+    fm_s32 ret = 0;
+    fm_u16 tmp_hex;
+    fm_s32 tmp_dec;
+
+       //WCN_DBG(FM_NTC|MAIN,"src_key=%s,src_val=%s\n", src_key,src_val);
+       //WCN_DBG(FM_NTC|MAIN,"dst_key=%s\n", dst_key);
+    if (strcmp(src_key, dst_key) == 0) {
+        if (strncmp(src_val, "0x", strlen("0x")) == 0) {
+            src_val += strlen("0x");
+            //WCN_DBG(FM_NTC|MAIN,"%s\n", src_val);
+            ret = ascii_to_hex(src_val, &tmp_hex);
+
+            if (!ret) {
+                *dst_val = tmp_hex;
+                //WCN_DBG(FM_NTC|MAIN, "%s 0x%04x\n", dst_key, tmp_hex);
+                return 0;
+            } else {
+                //WCN_DBG(FM_ERR | MAIN, "%s format error\n", dst_key);
+                return 1;
+            }
+        } else {
+            ret = ascii_to_dec(src_val, &tmp_dec);
+
+            if (!ret /*&& ((0 <= tmp_dec) && (tmp_dec <= 0xFFFF))*/) {
+                *dst_val = tmp_dec;
+                //WCN_DBG(FM_NTC|MAIN, "%s %d\n", dst_key, tmp_dec);
+                return 0;
+            } else {
+                //WCN_DBG(FM_ERR | MAIN, "%s format error\n", dst_key);
+                return 1;
+            }
+        }
+    }
+    //else
+    //{
+       //      WCN_DBG(FM_ERR | MAIN, "src_key!=dst_key\n");
+    //}
+
+    return -1;
+}
+
+static fm_s32 cfg_item_handler(fm_s8 *grp, fm_s8 *key, fm_s8 *val, fm_cust_cfg *cfg)
+{
+    fm_s32 ret = 0;
+    struct fm_rx_cust_cfg *rx_cfg = &cfg->rx_cfg;
+    struct fm_tx_cust_cfg *tx_cfg = &cfg->tx_cfg;
+
+    if (0 <= (ret = cfg_item_match(key, val, "FMR_RSSI_TH_L", &rx_cfg->long_ana_rssi_th))) {//FMR_RSSI_TH_L = 0x0301
+        return ret;
+    } else if (0 <= (ret = cfg_item_match(key, val, "FMR_RSSI_TH_S", &rx_cfg->short_ana_rssi_th))) {
+        return ret;
+    } else if (0 <= (ret = cfg_item_match(key, val, "FMR_CQI_TH", &rx_cfg->cqi_th))) {
+        return ret;
+    } else if (0 <= (ret = cfg_item_match(key, val, "FMR_MR_TH", &rx_cfg->mr_th))) {
+        return ret;
+    } else if (0 <= (ret = cfg_item_match(key, val, "FMR_SMG_TH", &rx_cfg->smg_th))) {
+        return ret;
+    } else if (0 <= (ret = cfg_item_match(key, val, "FMR_SCAN_CH_SIZE", &rx_cfg->scan_ch_size))) {
+        return ret;
+    } else if (0 <= (ret = cfg_item_match(key, val, "FMR_SCAN_SORT", &rx_cfg->scan_sort))) {
+        return ret;
+    } else if (0 <= (ret = cfg_item_match(key, val, "FMR_SEEK_SPACE", &rx_cfg->seek_space))) {
+        return ret;
+    } else if (0 <= (ret = cfg_item_match(key, val, "FMR_BAND", &rx_cfg->band))) {
+        return ret;
+    } else if (0 <= (ret = cfg_item_match(key, val, "FMR_BAND_FREQ_L", &rx_cfg->band_freq_l))) {
+        return ret;
+    } else if (0 <= (ret = cfg_item_match(key, val, "FMR_BAND_FREQ_H", &rx_cfg->band_freq_h))) {
+        return ret;
+    } else if (0 <= (ret = cfg_item_match(key, val, "FMR_FAKE_CH", &rx_cfg->fake_ch[fm_index]))) {
+        fm_index += 1;
+        rx_cfg->fake_ch_num = (rx_cfg->fake_ch_num < fm_index) ? fm_index : rx_cfg->fake_ch_num;
+        return ret;
+    } else if (0 <= (ret = cfg_item_match(key, val, "FMR_FAKE_CH_RSSI", &rx_cfg->fake_ch_rssi_th))) {
+        return ret;
+    } else if (0 <= (ret = cfg_item_match(key, val, "FMR_DEEMPHASIS", &rx_cfg->deemphasis))) {
+        return ret;
+    } else if (0 <= (ret = cfg_item_match(key, val, "FMR_OSC_FREQ", &rx_cfg->osc_freq))) {
+        return ret;
+    } else if (0 <= (ret = cfg_item_match(key, val, "FMT_SCAN_HOLE_L", &tx_cfg->scan_hole_low))) {
+        return ret;
+    } else if (0 <= (ret = cfg_item_match(key, val, "FMT_SCAN_HOLE_H", &tx_cfg->scan_hole_high))) {
+        return ret;
+    } else if (0 <= (ret = cfg_item_match(key, val, "FMT_PWR_LVL_MAX", &tx_cfg->power_level))) {
+        return ret;
+    } else {
+        WCN_DBG(FM_WAR | MAIN, "invalid key\n");
+        return -1;
+    }
+}
+
+static fm_s32 fm_cust_config_default(fm_cust_cfg *cfg)
+{
+    FMR_ASSERT(cfg);
+#if (!defined(MT6628_FM)&&!defined(MT6620_FM))
+
+    cfg->rx_cfg.long_ana_rssi_th = FM_RX_RSSI_TH_LONG;
+    cfg->rx_cfg.short_ana_rssi_th = FM_RX_RSSI_TH_SHORT;
+    cfg->rx_cfg.cqi_th = FM_RX_CQI_TH;
+    cfg->rx_cfg.mr_th = FM_RX_MR_TH;
+    cfg->rx_cfg.smg_th = FM_RX_SMG_TH;
+    cfg->rx_cfg.scan_ch_size = FM_RX_SCAN_CH_SIZE;
+    cfg->rx_cfg.seek_space = FM_RX_SEEK_SPACE;
+    cfg->rx_cfg.band = FM_RX_BAND;
+    cfg->rx_cfg.band_freq_l = FM_RX_BAND_FREQ_L;
+    cfg->rx_cfg.band_freq_h = FM_RX_BAND_FREQ_H;
+    cfg->rx_cfg.scan_sort = FM_RX_SCAN_SORT_SELECT;
+    cfg->rx_cfg.fake_ch_num = FM_RX_FAKE_CH_NUM;
+    cfg->rx_cfg.fake_ch_rssi_th = FM_RX_FAKE_CH_RSSI;
+    cfg->rx_cfg.fake_ch[0] = FM_RX_FAKE_CH_1;
+    cfg->rx_cfg.fake_ch[1] = FM_RX_FAKE_CH_2;
+    cfg->rx_cfg.fake_ch[2] = FM_RX_FAKE_CH_3;
+    cfg->rx_cfg.fake_ch[3] = FM_RX_FAKE_CH_4;
+    cfg->rx_cfg.fake_ch[4] = FM_RX_FAKE_CH_5;
+    cfg->rx_cfg.deemphasis = FM_RX_DEEMPHASIS;
+
+    cfg->tx_cfg.scan_hole_low = FM_TX_SCAN_HOLE_LOW;
+    cfg->tx_cfg.scan_hole_high = FM_TX_SCAN_HOLE_HIGH;
+    cfg->tx_cfg.power_level = FM_TX_PWR_LEVEL_MAX;
+#endif
+    return 0;
+}
+
+static fm_s32 fm_cust_config_file(const fm_s8 *filename, fm_cust_cfg *cfg)
+{
+    fm_s32 ret = 0;
+    fm_s8 *buf = NULL;
+    fm_s32 file_len = 0;
+
+    if (!(buf = fm_zalloc(4096))) {
+        WCN_DBG(FM_ALT | MAIN, "-ENOMEM\n");
+        return -ENOMEM;
+    }
+
+    fm_index = 0;
+
+    file_len = fm_file_read(filename, buf, 4096, 0);
+
+    if (file_len <= 0) {
+        ret = -1;
+        goto out;
+    }
+
+    ret = cfg_parser(buf, cfg_item_handler, cfg);
+
+out:
+
+    if (buf) {
+        fm_free(buf);
+    }
+
+    return ret;
+}
+
+static fm_s32 fm_cust_config_print(fm_cust_cfg *cfg)
+{
+    fm_s32 i;
+
+    WCN_DBG(FM_NTC | MAIN, "rssi_l:\t0x%04x\n", cfg->rx_cfg.long_ana_rssi_th);
+    WCN_DBG(FM_NTC | MAIN, "rssi_s:\t0x%04x\n", cfg->rx_cfg.short_ana_rssi_th);
+    WCN_DBG(FM_NTC | MAIN, "mr_th:\t0x%04x\n", cfg->rx_cfg.mr_th);
+    WCN_DBG(FM_NTC | MAIN, "cqi_th:\t0x%04x\n", cfg->rx_cfg.cqi_th);
+    WCN_DBG(FM_NTC | MAIN, "smg_th:\t0x%04x\n", cfg->rx_cfg.smg_th);
+    WCN_DBG(FM_NTC | MAIN, "scan_ch_size:\t%d\n", cfg->rx_cfg.scan_ch_size);
+    WCN_DBG(FM_NTC | MAIN, "seek_space:\t%d\n", cfg->rx_cfg.seek_space);
+    WCN_DBG(FM_NTC | MAIN, "band:\t%d\n", cfg->rx_cfg.band);
+    WCN_DBG(FM_NTC | MAIN, "band_freq_l:\t%d\n", cfg->rx_cfg.band_freq_l);
+    WCN_DBG(FM_NTC | MAIN, "band_freq_h:\t%d\n", cfg->rx_cfg.band_freq_h);
+    WCN_DBG(FM_NTC | MAIN, "scan_sort:\t%d\n", cfg->rx_cfg.scan_sort);
+    WCN_DBG(FM_NTC | MAIN, "fake_ch_num:\t%d\n", cfg->rx_cfg.fake_ch_num);
+    WCN_DBG(FM_NTC | MAIN, "fake_ch_rssi_th:\t%d\n", cfg->rx_cfg.fake_ch_rssi_th);
+
+    for (i = 0; i < cfg->rx_cfg.fake_ch_num; i++) {
+        WCN_DBG(FM_NTC | MAIN, "fake_ch:\t%d\n", cfg->rx_cfg.fake_ch[i]);
+    }
+
+    WCN_DBG(FM_NTC | MAIN, "de_emphasis:\t%d\n", cfg->rx_cfg.deemphasis);
+    WCN_DBG(FM_NTC | MAIN, "osc_freq:\t%d\n", cfg->rx_cfg.osc_freq);
+    WCN_DBG(FM_NTC | MAIN, "scan_hole_low:\t%d\n", cfg->tx_cfg.scan_hole_low);
+    WCN_DBG(FM_NTC | MAIN, "scan_hole_high:\t%d\n", cfg->tx_cfg.scan_hole_high);
+    WCN_DBG(FM_NTC | MAIN, "power_level:\t%d\n", cfg->tx_cfg.power_level);
+
+    return 0;
+}
+fm_s32 fm_cust_config(const fm_s8 *filepath)
+{
+    fm_s32 ret = 0;
+    fm_s8 *filep = NULL;
+    fm_s8 file_path[51] = {0};
+
+    fm_cust_config_default(&fm_config);
+    WCN_DBG(FM_NTC | MAIN, "FM default config\n");
+    fm_cust_config_print(&fm_config);
+
+    if (!filepath) {
+        filep = FM_CUST_CFG_PATH;
+    } else {
+        memcpy(file_path, filepath, (strlen(filepath) > 50) ? 50 : strlen(filepath));
+        filep = file_path;
+        trim_path(&filep);
+    }
+
+    ret = fm_cust_config_file(filep, &fm_config);
+    WCN_DBG(FM_NTC | MAIN, "FM cust config\n");
+    fm_cust_config_print(&fm_config);
+    return ret;
+}
+
+fm_u16 fm_cust_config_fetch(enum fm_cust_cfg_op op_code)
+{
+    fm_u16 tmp = 0;
+    fm_s32 i;
+    static fm_s32 fake_ch_idx = 0;
+
+    switch (op_code) {
+        //For FM RX
+    case FM_CFG_RX_RSSI_TH_LONG: {
+        tmp = fm_config.rx_cfg.long_ana_rssi_th;
+        break;
+    }
+    case FM_CFG_RX_RSSI_TH_SHORT: {
+        tmp = fm_config.rx_cfg.short_ana_rssi_th;
+        break;
+    }
+    case FM_CFG_RX_CQI_TH: {
+        tmp = fm_config.rx_cfg.cqi_th;
+        break;
+    }
+    case FM_CFG_RX_MR_TH: {
+        tmp = fm_config.rx_cfg.mr_th;
+        break;
+    }
+    case FM_CFG_RX_SMG_TH: {
+        tmp = fm_config.rx_cfg.smg_th;
+        break;
+    }
+    case FM_CFG_RX_SCAN_CH_SIZE: {
+        tmp = fm_config.rx_cfg.scan_ch_size;
+        break;
+    }
+    case FM_CFG_RX_SEEK_SPACE: {
+        tmp = fm_config.rx_cfg.seek_space;
+        break;
+    }
+    case FM_CFG_RX_BAND: {
+        tmp = fm_config.rx_cfg.band;
+        break;
+    }
+    case FM_CFG_RX_BAND_FREQ_L: {
+        tmp = fm_config.rx_cfg.band_freq_l;
+        break;
+    }
+    case FM_CFG_RX_BAND_FREQ_H: {
+        tmp = fm_config.rx_cfg.band_freq_h;
+        break;
+    }
+    case FM_CFG_RX_SCAN_SORT: {
+        tmp = fm_config.rx_cfg.scan_sort;
+        break;
+    }
+    case FM_CFG_RX_FAKE_CH_NUM: {
+        tmp = fm_config.rx_cfg.fake_ch_num;
+        break;
+    }
+    case FM_CFG_RX_FAKE_CH: {
+        tmp = fm_config.rx_cfg.fake_ch[fake_ch_idx];
+        i = (fm_config.rx_cfg.fake_ch_num > 0) ? fm_config.rx_cfg.fake_ch_num : FAKE_CH_MAX;
+        fake_ch_idx++;
+        fake_ch_idx = fake_ch_idx % i;
+        break;
+    }
+    case FM_CFG_RX_FAKE_CH_RSSI: {
+        tmp = fm_config.rx_cfg.fake_ch_rssi_th;
+        break;
+    }
+    case FM_CFG_RX_DEEMPHASIS: {
+        tmp = fm_config.rx_cfg.deemphasis;
+        break;
+    }
+    case FM_CFG_RX_OSC_FREQ: {
+        tmp = fm_config.rx_cfg.osc_freq;
+        break;
+    }
+    //For FM TX
+    case FM_CFG_TX_SCAN_HOLE_LOW: {
+        tmp = fm_config.tx_cfg.scan_hole_low;
+        break;
+    }
+    case FM_CFG_TX_SCAN_HOLE_HIGH: {
+        tmp = fm_config.tx_cfg.scan_hole_high;
+        break;
+    }
+    case FM_CFG_TX_PWR_LEVEL: {
+        tmp = fm_config.tx_cfg.power_level;
+        break;
+    }
+    default:
+        break;
+    }
+
+    WCN_DBG(FM_DBG | MAIN, "cust cfg %d: 0x%04x\n", op_code, tmp);
+    return tmp;
+}
diff --git a/drivers/mtk_wcn_combo/drv_fm/core/fm_eint.c b/drivers/mtk_wcn_combo/drv_fm/core/fm_eint.c
new file mode 100755 (executable)
index 0000000..23fd4e4
--- /dev/null
@@ -0,0 +1,55 @@
+/* mt6620_fm_eint.c
+ *
+ * (C) Copyright 2009 
+ * MediaTek <www.MediaTek.com>
+ * Run <Run.Liu@MediaTek.com>
+ *
+ * WCN combo chip FM Radio Driver -- EINT functions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#if (defined(MT6620_FM)||defined(MT6628_FM))
+#include "stp_exp.h"
+#include "wmt_exp.h"
+
+#include "fm_typedef.h"
+#include "fm_dbg.h"
+#include "fm_err.h"
+#include "fm_eint.h"
+       
+fm_s32 fm_enable_eint(void)
+{
+       return 0;
+}
+
+fm_s32 fm_disable_eint(void)
+{
+       return 0;
+}
+
+fm_s32 fm_request_eint(void (*parser)(void))
+{
+    WCN_DBG(FM_NTC|EINT,"%s\n", __func__);
+
+    mtk_wcn_stp_register_event_cb(FM_TASK_INDX, parser);
+    
+       return 0;
+}
+
+fm_s32 fm_eint_pin_cfg(fm_s32 mode)
+{      
+       return 0;
+}
+#endif
diff --git a/drivers/mtk_wcn_combo/drv_fm/core/fm_link.c b/drivers/mtk_wcn_combo/drv_fm/core/fm_link.c
new file mode 100755 (executable)
index 0000000..30a0ec0
--- /dev/null
@@ -0,0 +1,550 @@
+/* fm_link.c
+ *
+ * (C) Copyright 2012
+ * MediaTek <www.MediaTek.com>
+ * Hongcheng <hongcheng.xia@MediaTek.com>
+ *
+ * FM Radio Driver -- setup data link common part
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+
+#include "fm_typedef.h"
+#include "fm_dbg.h"
+#include "fm_err.h"
+#include "fm_stdlib.h"
+#include "fm_link.h"
+#if (defined(MT6620_FM)||defined(MT6628_FM))
+#include "stp_exp.h"
+#include "wmt_exp.h"
+static struct fm_link_event *link_event;
+
+static struct fm_trace_fifo_t *cmd_fifo;
+
+static struct fm_trace_fifo_t *evt_fifo;
+    
+static fm_s32 (*reset)(fm_s32 sta) = NULL;
+
+static void WCNfm_wholechip_rst_cb(ENUM_WMTDRV_TYPE_T src,
+                                ENUM_WMTDRV_TYPE_T dst,
+                                ENUM_WMTMSG_TYPE_T type,
+                                void *buf,
+                                unsigned int sz)
+{
+    //To handle reset procedure please
+    ENUM_WMTRSTMSG_TYPE_T rst_msg;
+    
+    if (sz <= sizeof(ENUM_WMTRSTMSG_TYPE_T)) {
+        memcpy((char *)&rst_msg, (char *)buf, sz);
+        WCN_DBG(FM_WAR | LINK, "[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_FM) && (type == WMTMSG_TYPE_RESET)) {
+            if (rst_msg == WMTRSTMSG_RESET_START) {
+                WCN_DBG(FM_WAR | LINK, "FM restart start!\n");
+                if (reset) {
+                    reset(1);
+                }
+                
+            } else if (rst_msg == WMTRSTMSG_RESET_END) {
+                WCN_DBG(FM_WAR | LINK, "FM restart end!\n");
+                if (reset) {
+                    reset(0);
+                }
+            }
+        }
+    } else {
+        /*message format invalid*/
+        WCN_DBG(FM_WAR | LINK, "message format invalid!\n");
+    }
+}
+
+    
+fm_s32 fm_link_setup(void* data)
+{
+    fm_s32 ret = 0;
+    
+    if (!(link_event = fm_zalloc(sizeof(struct fm_link_event)))) {
+        WCN_DBG(FM_ALT | LINK, "fm_zalloc(fm_link_event) -ENOMEM\n");
+        return -1;
+    }
+
+    link_event->ln_event = fm_flag_event_create("ln_evt");
+
+    if (!link_event->ln_event) {
+        WCN_DBG(FM_ALT | LINK, "create mt6620_ln_event failed\n");
+        fm_free(link_event);
+        return -1;
+    }
+
+    fm_flag_event_get(link_event->ln_event);
+
+
+    WCN_DBG(FM_NTC | LINK, "fm link setup\n");
+
+    cmd_fifo = fm_trace_fifo_create("cmd_fifo");
+    if (!cmd_fifo) {
+        WCN_DBG(FM_ALT | LINK, "create cmd_fifo failed\n");
+        ret = -1;
+        goto failed;
+    }
+    
+    evt_fifo = fm_trace_fifo_create("evt_fifo");
+    if (!evt_fifo) {
+        WCN_DBG(FM_ALT | LINK, "create evt_fifo failed\n");
+        ret = -1;
+        goto failed;
+    }
+    
+    reset = data; // get whole chip reset cb
+    mtk_wcn_wmt_msgcb_reg(WMTDRV_TYPE_FM, WCNfm_wholechip_rst_cb);
+    return 0;
+    
+failed:
+    fm_trace_fifo_release(evt_fifo);
+    fm_trace_fifo_release(cmd_fifo);
+    fm_flag_event_put(link_event->ln_event);
+    if (link_event) {
+        fm_free(link_event);
+    }
+    
+    return ret;
+}
+
+fm_s32 fm_link_release(void)
+{
+
+    fm_trace_fifo_release(evt_fifo);
+    fm_trace_fifo_release(cmd_fifo);
+    fm_flag_event_put(link_event->ln_event);
+    if (link_event) {
+        fm_free(link_event);
+    }
+
+    WCN_DBG(FM_NTC | LINK, "fm link release\n");
+    return 0;
+}
+
+/*
+ * fm_ctrl_rx
+ * the low level func to read a rigister
+ * @addr - rigister address
+ * @val - the pointer of target buf
+ * If success, return 0; else error code
+ */
+fm_s32 fm_ctrl_rx(fm_u8 addr, fm_u16 *val)
+{
+    return 0;
+}
+
+/*
+ * fm_ctrl_tx
+ * the low level func to write a rigister
+ * @addr - rigister address
+ * @val - value will be writed in the rigister
+ * If success, return 0; else error code
+ */
+fm_s32 fm_ctrl_tx(fm_u8 addr, fm_u16 val)
+{
+    return 0;
+}
+
+/*
+ * fm_cmd_tx() - send cmd to FM firmware and wait event
+ * @buf - send buffer
+ * @len - the length of cmd
+ * @mask - the event flag mask
+ * @   cnt - the retry conter
+ * @timeout - timeout per cmd
+ * Return 0, if success; error code, if failed
+ */
+fm_s32 fm_cmd_tx(fm_u8* buf, fm_u16 len, fm_s32 mask, fm_s32 cnt, fm_s32 timeout, fm_s32(*callback)(struct fm_res_ctx* result))
+{
+    fm_s32 ret_time = 0;
+    struct task_struct *task = current;
+    struct fm_trace_t trace;
+
+    if ((NULL == buf) || (len < 0) || (0 == mask)
+            || (cnt > SW_RETRY_CNT_MAX) || (timeout > SW_WAIT_TIMEOUT_MAX)) {
+        WCN_DBG(FM_ERR | LINK, "cmd tx, invalid para\n");
+        return -FM_EPARA;
+    }
+
+    FM_EVENT_CLR(link_event->ln_event, mask);
+    
+#ifdef FM_TRACE_ENABLE
+    trace.type = buf[0];
+    trace.opcode = buf[1];
+    trace.len = len - 4;
+    trace.tid = (fm_s32)task->pid;
+    fm_memset(trace.pkt, 0, FM_TRACE_PKT_SIZE);
+    fm_memcpy(trace.pkt, &buf[4], (trace.len > FM_TRACE_PKT_SIZE) ? FM_TRACE_PKT_SIZE : trace.len);
+#endif
+
+sw_retry:
+
+#ifdef FM_TRACE_ENABLE
+    if (fm_true == FM_TRACE_FULL(cmd_fifo)) {
+        FM_TRACE_OUT(cmd_fifo, NULL);
+    }
+    FM_TRACE_IN(cmd_fifo, &trace);
+#endif
+
+    //send cmd to FM firmware
+    if ((ret_time = mtk_wcn_stp_send_data(buf, len, FM_TASK_INDX)) <= 0) 
+       {
+        WCN_DBG(FM_EMG | LINK, "send data over stp failed[%d]\n",ret_time);
+        return -FM_ELINK;
+    }
+
+    //wait the response form FM firmware
+    ret_time = FM_EVENT_WAIT_TIMEOUT(link_event->ln_event, mask, timeout);
+
+    if (!ret_time) {
+        if (0 < cnt--) {
+            WCN_DBG(FM_WAR | LINK, "wait even timeout, [retry_cnt=%d], pid=%d\n", cnt, task->pid);
+            fm_print_cmd_fifo();
+            fm_print_evt_fifo();
+            return -FM_EFW;
+            goto sw_retry; //retry if timeout and retry cnt > 0
+        } else {
+            WCN_DBG(FM_ALT | LINK, "fatal error, SW retry failed, reset HW\n");
+            return -FM_EFW;
+        }
+    }
+
+    FM_EVENT_CLR(link_event->ln_event, mask);
+
+    if (callback) {
+        callback(&link_event->result);
+    }
+
+    return 0;
+}
+
+fm_s32 fm_event_parser(fm_s32(*rds_parser)(struct rds_rx_t*, fm_s32))
+{
+    fm_s32 len;
+    fm_s32 i = 0;
+    fm_u8 opcode = 0;
+    fm_u16 length = 0;
+    fm_u8 ch;
+    fm_u8 rx_buf[RX_BUF_SIZE + 10] = {0}; //the 10 bytes are protect gaps
+    static volatile fm_task_parser_state state = FM_TASK_RX_PARSER_PKT_TYPE;
+    struct fm_trace_t trace;
+    struct task_struct *task = current;
+
+    len = mtk_wcn_stp_receive_data(rx_buf, RX_BUF_SIZE, FM_TASK_INDX);
+    WCN_DBG(FM_DBG | LINK, "[len=%d],[CMD=0x%02x 0x%02x 0x%02x 0x%02x]\n", len, rx_buf[0], rx_buf[1], rx_buf[2], rx_buf[3]);
+
+    while (i < len) {
+        ch = rx_buf[i];
+
+        switch (state) {
+        case FM_TASK_RX_PARSER_PKT_TYPE:
+
+            if (ch == FM_TASK_EVENT_PKT_TYPE) {
+                if ((i + 5) < RX_BUF_SIZE) {
+                    WCN_DBG(FM_DBG | LINK, "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x \n", rx_buf[i], rx_buf[i+1], rx_buf[i+2], rx_buf[i+3], rx_buf[i+4], rx_buf[i+5]);
+                } else {
+                    WCN_DBG(FM_DBG | LINK, "0x%02x 0x%02x\n", rx_buf[i], rx_buf[i+1]);
+                }
+
+                state = FM_TASK_RX_PARSER_OPCODE;
+            } else {
+                WCN_DBG(FM_ALT | LINK, "event pkt type error (rx_buf[%d] = 0x%02x)\n", i, ch);
+            }
+
+            i++;
+            break;
+
+        case FM_TASK_RX_PARSER_OPCODE:
+            i++;
+            opcode = ch;
+            state = FM_TASK_RX_PARSER_PKT_LEN_1;
+            break;
+
+        case FM_TASK_RX_PARSER_PKT_LEN_1:
+            i++;
+            length = ch;
+            state = FM_TASK_RX_PARSER_PKT_LEN_2;
+            break;
+
+        case FM_TASK_RX_PARSER_PKT_LEN_2:
+            i++;
+            length |= (fm_u16)(ch << 0x8);
+
+#ifdef FM_TRACE_ENABLE
+            trace.type = FM_TASK_EVENT_PKT_TYPE;
+            trace.opcode = opcode;
+            trace.len = length;
+            trace.tid = (fm_s32)task->pid;
+            fm_memset(trace.pkt, 0, FM_TRACE_PKT_SIZE);
+            fm_memcpy(trace.pkt, &rx_buf[i], (length > FM_TRACE_PKT_SIZE) ? FM_TRACE_PKT_SIZE : length);
+
+            if (fm_true == FM_TRACE_FULL(cmd_fifo)) {
+                FM_TRACE_OUT(cmd_fifo, NULL);
+            }
+            FM_TRACE_IN(cmd_fifo, &trace);
+#endif
+            if (length > 0) {
+                state = FM_TASK_RX_PARSER_PKT_PAYLOAD;
+            } else {
+                state = FM_TASK_RX_PARSER_PKT_TYPE;
+                FM_EVENT_SEND(link_event->ln_event, (1 << opcode));
+            }
+
+            break;
+
+        case FM_TASK_RX_PARSER_PKT_PAYLOAD:
+
+            switch (opcode) {
+            case FM_TUNE_OPCODE:
+
+                if ((length == 1) && (rx_buf[i] == 1)) {
+                    FM_EVENT_SEND(link_event->ln_event, FLAG_TUNE_DONE);
+                }
+
+                break;
+
+            case FM_SOFT_MUTE_TUNE_OPCODE:
+
+                if (length >= 2) {
+                    fm_memcpy(link_event->result.cqi, &rx_buf[i], (length > FM_CQI_BUF_SIZE) ? FM_CQI_BUF_SIZE : length);
+                    FM_EVENT_SEND(link_event->ln_event, FLAG_SM_TUNE);
+                }
+                break;
+                
+            case FM_SEEK_OPCODE:
+
+                if ((i + 1) < RX_BUF_SIZE) {
+                    link_event->result.seek_result = rx_buf[i] + (rx_buf[i+1] << 8); // 8760 means 87.60Mhz
+                }
+
+                FM_EVENT_SEND(link_event->ln_event, FLAG_SEEK_DONE);
+                break;
+
+            case FM_SCAN_OPCODE:
+
+                //check if the result data is long enough
+                if ((RX_BUF_SIZE - i) < (sizeof(fm_u16) * FM_SCANTBL_SIZE)) {
+                    WCN_DBG(FM_ALT | LINK, "FM_SCAN_OPCODE err, [tblsize=%d],[bufsize=%d]\n", (sizeof(fm_u16) * FM_SCANTBL_SIZE), (RX_BUF_SIZE - i));
+                    FM_EVENT_SEND(link_event->ln_event, FLAG_SCAN_DONE);
+                    return 0;
+                } else if ((length >= FM_CQI_BUF_SIZE) && ((RX_BUF_SIZE - i) >= FM_CQI_BUF_SIZE)) {
+                    fm_memcpy(link_event->result.cqi, &rx_buf[i], FM_CQI_BUF_SIZE);
+                    FM_EVENT_SEND(link_event->ln_event, FLAG_CQI_DONE);
+                } else {
+                    fm_memcpy(link_event->result.scan_result, &rx_buf[i], sizeof(fm_u16) * FM_SCANTBL_SIZE);
+                    FM_EVENT_SEND(link_event->ln_event, FLAG_SCAN_DONE);
+                }
+
+                break;
+
+            case FSPI_READ_OPCODE:
+
+                if ((i + 1) < RX_BUF_SIZE) {
+                    link_event->result.fspi_rd = (rx_buf[i] + (rx_buf[i+1] << 8));
+                }
+
+                FM_EVENT_SEND(link_event->ln_event, (1 << opcode));
+                break;
+
+            case RDS_RX_DATA_OPCODE:
+
+                //check if the rds data is long enough
+                if ((RX_BUF_SIZE - i) < length) {
+                    WCN_DBG(FM_ALT | LINK, "RDS RX err, [rxlen=%d],[bufsize=%d]\n", (fm_s32)length, (RX_BUF_SIZE - i));
+                    FM_EVENT_SEND(link_event->ln_event, (1 << opcode));
+                    break;
+                }
+
+                //copy rds data to rds buf
+                fm_memcpy(&link_event->result.rds_rx_result, &rx_buf[i], length);
+
+                /*Handle the RDS data that we get*/
+                if (rds_parser) {
+                    rds_parser(&link_event->result.rds_rx_result, length);
+                } else {
+                    WCN_DBG(FM_WAR | LINK, "no method to parse RDS data\n");
+                }
+
+                FM_EVENT_SEND(link_event->ln_event, (1 << opcode));
+                break;
+
+            default:
+                FM_EVENT_SEND(link_event->ln_event, (1 << opcode));
+                break;
+            }
+
+            state = FM_TASK_RX_PARSER_PKT_TYPE;
+            i += length;
+            break;
+
+        default:
+            break;
+        }
+    }
+
+    return 0;
+}
+
+fm_bool fm_wait_stc_done(fm_u32 sec)
+{
+    return fm_true;
+}
+
+fm_s32 fm_force_active_event(fm_u32 mask)
+{
+    fm_u32 flag;
+
+    flag = FM_EVENT_GET(link_event->ln_event);
+    WCN_DBG(FM_WAR | LINK, "before force active event, [flag=0x%08x]\n", flag);
+    flag = FM_EVENT_SEND(link_event->ln_event, mask);
+    WCN_DBG(FM_WAR | LINK, "after force active event, [flag=0x%08x]\n", flag);
+
+    return 0;
+}
+
+
+extern fm_s32 fm_print_cmd_fifo(void)
+{
+#ifdef FM_TRACE_ENABLE
+    struct fm_trace_t trace;
+    fm_s32 i = 0;
+    
+    while (fm_false == FM_TRACE_EMPTY(cmd_fifo)) {
+        fm_memset(trace.pkt, 0, FM_TRACE_PKT_SIZE);
+        FM_TRACE_OUT(cmd_fifo, &trace);
+        WCN_DBG(FM_ALT | LINK, "trace, type %d, op %d, len %d, tid %d, time %d\n", trace.type, trace.opcode, trace.len, trace.tid, jiffies_to_msecs(abs(trace.time)));
+        i = 0;
+        while ((trace.len > 0) && (i < trace.len) && (i < (FM_TRACE_PKT_SIZE-8))) {
+            WCN_DBG(FM_ALT | LINK, "trace, %02x %02x %02x %02x %02x %02x %02x %02x\n", \
+                trace.pkt[i], trace.pkt[i+1], trace.pkt[i+2], trace.pkt[i+3], trace.pkt[i+4], trace.pkt[i+5], trace.pkt[i+6], trace.pkt[i+7]);
+            i += 8;
+        }
+        WCN_DBG(FM_ALT | LINK, "trace\n");
+    }
+#endif
+
+    return 0;
+}
+
+extern fm_s32 fm_print_evt_fifo(void)
+{
+#ifdef FM_TRACE_ENABLE
+    struct fm_trace_t trace;
+    fm_s32 i = 0;
+    
+    while (fm_false == FM_TRACE_EMPTY(evt_fifo)) {
+        fm_memset(trace.pkt, 0, FM_TRACE_PKT_SIZE);
+        FM_TRACE_OUT(evt_fifo, &trace);
+        WCN_DBG(FM_ALT | LINK, "%s: op %d, len %d, %d\n", evt_fifo->name, trace.opcode, trace.len, jiffies_to_msecs(abs(trace.time)));
+        i = 0;
+        while ((trace.len > 0) && (i < trace.len) && (i < (FM_TRACE_PKT_SIZE-8))) {
+            WCN_DBG(FM_ALT | LINK, "%s: %02x %02x %02x %02x %02x %02x %02x %02x\n", \
+                evt_fifo->name, trace.pkt[i], trace.pkt[i+1], trace.pkt[i+2], trace.pkt[i+3], trace.pkt[i+4], trace.pkt[i+5], trace.pkt[i+6], trace.pkt[i+7]);
+            i += 8;
+        }
+        WCN_DBG(FM_ALT | LINK, "%s\n", evt_fifo->name);
+    }
+#endif
+
+    return 0;
+}
+#endif
+
+fm_s32 fm_trace_in(struct fm_trace_fifo_t *thiz, struct fm_trace_t *new_tra)
+{
+    FMR_ASSERT(new_tra);
+
+    if (thiz->len < thiz->size) {
+        fm_memcpy(&(thiz->trace[thiz->in]), new_tra, sizeof(struct fm_trace_t));
+        thiz->trace[thiz->in].time = jiffies;
+        thiz->in = (thiz->in + 1) % thiz->size;
+        thiz->len++;
+        //WCN_DBG(FM_DBG | RDSC, "add a new tra[len=%d]\n", thiz->len);
+    } else {
+        WCN_DBG(FM_WAR | RDSC, "tra buf is full\n");
+        return -FM_ENOMEM;
+    }
+
+    return 0;
+}
+
+fm_s32 fm_trace_out(struct fm_trace_fifo_t *thiz, struct fm_trace_t *dst_tra)
+{
+    if (thiz->len > 0) {
+        if (dst_tra) {
+            fm_memcpy(dst_tra, &(thiz->trace[thiz->out]), sizeof(struct fm_trace_t));
+            fm_memset(&(thiz->trace[thiz->out]), 0, sizeof(struct fm_trace_t));
+        }
+        thiz->out = (thiz->out + 1) % thiz->size;
+        thiz->len--;
+        //WCN_DBG(FM_DBG | RDSC, "del a tra[len=%d]\n", thiz->len);
+    } else {
+        WCN_DBG(FM_WAR | RDSC, "tra buf is empty\n");
+    }
+
+    return 0;
+}
+
+fm_bool fm_trace_is_full(struct fm_trace_fifo_t *thiz)
+{
+    return (thiz->len == thiz->size) ? fm_true : fm_false;
+}
+
+fm_bool fm_trace_is_empty(struct fm_trace_fifo_t *thiz)
+{
+    return (thiz->len == 0) ? fm_true : fm_false;
+}
+
+
+struct fm_trace_fifo_t* fm_trace_fifo_create(const fm_s8 *name) 
+{
+    struct fm_trace_fifo_t *tmp;
+
+    if (!(tmp = fm_zalloc(sizeof(struct fm_trace_fifo_t)))) {
+        WCN_DBG(FM_ALT | MAIN, "fm_zalloc(fm_trace_fifo) -ENOMEM\n");
+        return NULL;
+    }
+
+    fm_memcpy(tmp->name, name, 20);
+    tmp->size = FM_TRACE_FIFO_SIZE;
+    tmp->in = 0;
+    tmp->out = 0;
+    tmp->len = 0;
+    tmp->trace_in = fm_trace_in;
+    tmp->trace_out = fm_trace_out;
+    tmp->is_full = fm_trace_is_full;
+    tmp->is_empty = fm_trace_is_empty;
+    
+    WCN_DBG(FM_NTC | LINK, "%s created\n", tmp->name);
+
+    return tmp;
+}
+
+
+fm_s32 fm_trace_fifo_release(struct fm_trace_fifo_t *fifo) 
+{
+    if (fifo) {
+        WCN_DBG(FM_NTC | LINK, "%s released\n", fifo->name);
+        fm_free(fifo);
+    }
+
+    return 0;
+}
diff --git a/drivers/mtk_wcn_combo/drv_fm/core/fm_main.c b/drivers/mtk_wcn_combo/drv_fm/core/fm_main.c
new file mode 100755 (executable)
index 0000000..1637197
--- /dev/null
@@ -0,0 +1,2892 @@
+/* fm_main.c
+ *
+ * (C) Copyright 2011
+ * MediaTek <www.MediaTek.com>
+ * Hongcheng <hongcheng.xia@MediaTek.com>
+ *
+ * FM Radio Driver -- main functions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/kernel.h>
+#include <asm/uaccess.h>
+#include <linux/slab.h>
+
+#include "fm_main.h"
+#include "fm_config.h"
+//#include "fm_cust_cfg.h"
+#include "wmt_exp.h"
+//fm main data structure
+static struct fm *g_fm_struct = NULL;
+//we must get low level interface first, when add a new chip, the main effort is this interface
+static struct fm_lowlevel_ops fm_low_ops;
+#ifdef MT6620_FM
+static struct fm_lowlevel_ops MT6620fm_low_ops;
+#endif
+#ifdef MT6628_FM
+static struct fm_lowlevel_ops MT6628fm_low_ops;
+#endif
+//MTK FM Radio private advanced features
+#if 0//(!defined(MT6620_FM)&&!defined(MT6628_FM))
+static struct fm_priv priv_adv;
+#endif
+//mutex for char device ops
+static struct fm_lock *fm_ops_lock;
+//mutex for RDS parsing and read result
+static struct fm_lock *fm_read_lock;
+//for get rds block counter
+static struct fm_lock *fm_rds_cnt;
+//mutex for fm timer, RDS reset
+static struct fm_lock *fm_timer_lock;
+static struct fm_lock *fm_rxtx_lock;//protect FM RX TX mode switch 
+static struct fm_lock *fm_rtc_mutex;//protect FM GPS RTC drift info  
+
+static struct fm_timer *fm_timer_sys;
+
+static struct fm_i2s_info fm_i2s_inf = {
+    .status = 0,    //i2s off
+    .mode = 0,      //slave mode
+    .rate = 48000,  //48000 sample rate
+};
+
+static fm_bool scan_stop_flag = fm_false;
+static struct fm_gps_rtc_info gps_rtc_info;
+
+//RDS reset related functions
+static fm_u16 fm_cur_freq_get(void);
+static fm_s32 fm_cur_freq_set(fm_u16 new_freq);
+static enum fm_op_state fm_op_state_get(struct fm *fmp);
+static enum fm_op_state fm_op_state_set(struct fm *fmp, enum fm_op_state sta);
+static void fm_timer_func(unsigned long data);
+static void fmtx_timer_func(unsigned long data);
+
+static void fm_enable_rds_BlerCheck(struct fm *fm);
+static void fm_disable_rds_BlerCheck(void);
+static void fm_rds_reset_work_func(unsigned long data);
+//when interrupt be triggered by FM chip, fm_eint_handler will first be executed
+//then fm_eint_handler will schedule fm_eint_work_func to run
+static void fm_eint_handler(void);
+static void fm_eint_work_func(unsigned long data);
+static fm_s32 fm_rds_parser(struct rds_rx_t *rds_raw, fm_s32 rds_size);
+static fm_s32 fm_callback_register(struct fm_lowlevel_ops *ops);
+static fm_s32 fm_callback_unregister(struct fm_lowlevel_ops *ops);
+
+static fm_s32 pwrdown_flow(struct fm *fm);
+
+static         fm_u16 fm_cur_freq_get(void)
+{
+    return g_fm_struct ? g_fm_struct->cur_freq : 0;
+}
+
+static fm_s32 fm_cur_freq_set(fm_u16 new_freq)
+{
+    if (g_fm_struct)
+        g_fm_struct->cur_freq = new_freq;
+
+    return 0;
+}
+
+static enum fm_op_state fm_op_state_get(struct fm *fmp)
+{
+    if (fmp) {
+        WCN_DBG(FM_DBG | MAIN, "op state get %d\n", fmp->op_sta);
+        return fmp->op_sta;
+    } else {
+        WCN_DBG(FM_ERR | MAIN, "op state get para error\n");
+        return FM_STA_UNKOWN;
+    }
+}
+
+static enum fm_op_state fm_op_state_set(struct fm *fmp, enum fm_op_state sta)
+{
+    if (fmp && (sta < FM_STA_MAX)) {
+        fmp->op_sta = sta;
+        WCN_DBG(FM_DBG | MAIN, "op state set to %d\n", sta);
+        return fmp->op_sta;
+    } else {
+        WCN_DBG(FM_ERR | MAIN, "op state set para error, %d\n", sta);
+        return FM_STA_UNKOWN;
+    }
+}
+
+enum fm_pwr_state fm_pwr_state_get(struct fm *fmp)
+{
+    if (fmp) {
+        WCN_DBG(FM_DBG | MAIN, "pwr state get %d\n", fmp->pwr_sta);
+        return fmp->pwr_sta;
+    } else {
+        WCN_DBG(FM_ERR | MAIN, "pwr state get para error\n");
+        return FM_PWR_MAX;
+    }
+}
+
+enum fm_pwr_state fm_pwr_state_set(struct fm *fmp, enum fm_pwr_state sta)
+{
+    if (fmp && (sta < FM_PWR_MAX)) {
+        fmp->pwr_sta = sta;
+        WCN_DBG(FM_NTC | MAIN, "pwr state set to %d\n", sta);
+        return fmp->pwr_sta;
+    } else {
+        WCN_DBG(FM_ERR | MAIN, "pwr state set para error, %d\n", sta);
+        return FM_PWR_MAX;
+    }
+}
+
+static volatile fm_s32 subsys_rst_state = FM_SUBSYS_RST_OFF;
+
+fm_s32 fm_sys_state_get(struct fm *fmp)
+{
+    return subsys_rst_state;
+}
+
+fm_s32 fm_sys_state_set(struct fm *fmp, fm_s32 sta)
+{
+    if ((sta >= FM_SUBSYS_RST_OFF) && (sta < FM_SUBSYS_RST_MAX)) {
+        WCN_DBG(FM_NTC | MAIN, "sys state set from %d to %d\n", subsys_rst_state, sta);
+        subsys_rst_state = sta;
+    } else {
+        WCN_DBG(FM_ERR | MAIN, "sys state set para error, %d\n", sta);
+    }
+
+    return subsys_rst_state;
+}
+
+
+fm_s32 fm_subsys_reset(struct fm *fm)
+{
+    //check if we are resetting
+    if (fm_sys_state_get(fm) != FM_SUBSYS_RST_OFF) {
+        WCN_DBG(FM_NTC | MAIN, "subsys reset is ongoing\n");
+        goto out;
+    }
+
+    FMR_ASSERT(fm);
+    fm->timer_wkthd->add_work(fm->timer_wkthd, fm->rst_wk);
+
+out:
+    return 0;
+}
+
+
+fm_s32 fm_wholechip_rst_cb(fm_s32 sta)
+{
+    struct fm *fm = g_fm_struct;
+    
+    if (!fm) return 0;
+
+    if (sta == 1) { 
+        if (fm_sys_state_get(fm) == FM_SUBSYS_RST_OFF) {
+            fm_sys_state_set(fm, FM_SUBSYS_RST_START);
+        }
+    } else {
+        fm->timer_wkthd->add_work(fm->timer_wkthd, fm->rst_wk);
+    }
+    return 0;
+}
+
+
+fm_s32 fm_open(struct fm *fmp)
+{
+    fm_s32 ret = 0;
+#if (defined(MT6620_FM)||defined(MT6628_FM))
+    fm_s32 chipid;
+#endif
+    FMR_ASSERT(fmp);
+       if (current->pid == 1)
+               return 0;
+    if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+
+    //makesure fmp->ref >= 0
+    fmp->ref = (fmp->ref < 0) ? 0 : fmp->ref;
+    fmp->ref++;
+
+    if ((fmp->ref > 0) && (fmp->chipon == fm_false)) 
+       {
+#if (defined(MT6620_FM)||defined(MT6628_FM))
+               chipid = mtk_wcn_wmt_chipid_query();
+               WCN_DBG(FM_NTC | MAIN, "wmt chip id=0x%x\n",chipid);
+               if(chipid == 0x6628)//get WCN chip ID
+               {
+#ifdef MT6628_FM
+                       fm_low_ops = MT6628fm_low_ops;
+                       fmp->chip_id = 0x6628;
+                       WCN_DBG(FM_NTC | MAIN, "get 6628 low ops\n");
+#endif
+               }
+               else if(chipid == 0x6620)
+               {
+#ifdef MT6620_FM
+                       fm_low_ops = MT6620fm_low_ops;
+                       fmp->chip_id = 0x6620;
+                       WCN_DBG(FM_NTC | MAIN, "get 6620 low ops\n");
+#endif
+               }
+#endif
+               if(fm_low_ops.bi.pwron == NULL)
+               {
+                       WCN_DBG(FM_NTC | MAIN, "get fm_low_ops fail\n");
+            fmp->ref--;
+            ret = -ENODEV;
+            goto out;
+        }
+
+        ret = fm_low_ops.bi.pwron(0);
+        if (ret) {
+            fmp->ref--;
+            ret = -ENODEV;
+            goto out;
+        }
+
+        fm_eint_pin_cfg(FM_EINT_PIN_EINT_MODE);
+        fm_request_eint(fm_eint_handler);
+        fmp->chipon = fm_true;
+    }
+
+out:
+    WCN_DBG(FM_NTC | MAIN, "fm->ref:%d\n", fmp->ref);
+    FM_UNLOCK(fm_ops_lock);
+    return ret;
+}
+
+fm_s32 fm_close(struct fm *fmp)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(fmp);
+    if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+
+    fmp->ref--;
+
+    if (fmp->ref == 0) {
+        pwrdown_flow(fmp);
+        if (fmp->chipon == fm_true) {
+            fm_eint_pin_cfg(FM_EINT_PIN_GPIO_MODE);
+            fm_low_ops.bi.pwroff(0);
+            fmp->chipon = fm_false;
+        }
+    }
+
+    //makesure fm->ref >= 0
+    fmp->ref = (fmp->ref < 0) ? 0 : fmp->ref;
+    WCN_DBG(FM_NTC | MAIN, "fmp->ref:%d\n", fmp->ref);
+    FM_UNLOCK(fm_ops_lock);
+
+    return ret;
+}
+/*
+fm_s32 fm_flush(struct fm *fmp)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(fmp);
+    if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+
+    if (FM_PWR_OFF == fm_pwr_state_get(fmp)) 
+    {
+        WCN_DBG(FM_NTC | MAIN, "should power off combo!\n");
+        if (fmp->chipon == fm_true) 
+        {
+            fm_low_ops.bi.pwroff(0);
+            fmp->chipon = fm_false;
+        }
+    }
+    WCN_DBG(FM_NTC | MAIN, "fm_flush done\n");
+    FM_UNLOCK(fm_ops_lock);
+
+    return ret;
+}
+*/
+fm_s32 fm_rds_read(struct fm *fmp, fm_s8 *dst, fm_s32 len)
+{
+    fm_s32 copy_len = 0, left = 0;
+    copy_len = sizeof(rds_t);
+
+RESTART:
+
+    if (FM_EVENT_GET(fmp->rds_event) == FM_RDS_DATA_READY) {
+        if (FM_LOCK(fm_read_lock)) return (-FM_ELOCK);
+
+        if ((left = copy_to_user((void *)dst, fmp->pstRDSData, (unsigned long)copy_len))) {
+            WCN_DBG(FM_ALT | MAIN, "fm_read copy failed\n");
+        } else {
+            fmp->pstRDSData->event_status = 0x0000;
+        }
+
+        WCN_DBG(FM_DBG | MAIN, "fm_read copy len:%d\n", (copy_len - left));
+
+        FM_EVENT_RESET(fmp->rds_event);
+        FM_UNLOCK(fm_read_lock);
+    } else {
+        if (FM_EVENT_WAIT(fmp->rds_event, FM_RDS_DATA_READY) == 0) {
+            WCN_DBG(FM_DBG | MAIN, "fm_read wait ok\n");
+            goto RESTART;
+        } else {
+            WCN_DBG(FM_ALT | MAIN, "fm_read wait err\n");
+            return 0;
+        }
+    }
+
+    return (copy_len - left);
+}
+
+fm_s32 fm_powerup(struct fm *fm, struct fm_tune_parm *parm)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(fm_low_ops.bi.pwron);
+    FMR_ASSERT(fm_low_ops.bi.pwrupseq);
+    FMR_ASSERT(fm_low_ops.bi.low_pwr_wa);
+    if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+
+    //for normal case
+    if (fm->chipon == fm_false) {
+        fm_low_ops.bi.pwron(0);
+        fm->chipon = fm_true;
+    }
+
+    if (FM_PWR_RX_ON == fm_pwr_state_get(fm)) {
+        WCN_DBG(FM_NTC | MAIN, "already pwron!\n");
+        goto out;
+    }
+       else if(FM_PWR_TX_ON == fm_pwr_state_get(fm))
+       {
+        //if Tx is on, we need pwr down TX first
+        ret = fm_powerdowntx(fm);
+        if(ret)
+               {
+           WCN_DBG(FM_ERR | MAIN,"FM pwr down Tx fail!\n"); 
+           return ret;
+        }
+    }
+
+    fm_pwr_state_set(fm, FM_PWR_RX_ON);
+
+    //execute power on sequence
+    ret = fm_low_ops.bi.pwrupseq(&fm->chip_id, &fm->device_id);
+
+    if (ret) {
+        goto out;
+    }
+
+    fm_enable_eint();
+
+    WCN_DBG(FM_DBG | MAIN, "pwron ok\n");
+    fm_cur_freq_set(parm->freq);
+
+    parm->err = FM_SUCCESS;
+    fm_low_ops.bi.low_pwr_wa(1);
+
+    fm->vol = 15;
+       if(fm_low_ops.ri.rds_bci_get)
+       {
+               fm_timer_sys->init(fm_timer_sys, fm_timer_func, (unsigned long)g_fm_struct, fm_low_ops.ri.rds_bci_get(), 0);
+               fm_timer_sys->start(fm_timer_sys);
+               WCN_DBG(FM_NTC | MAIN, "start timer ok\n");
+       }
+       else
+       {
+               WCN_DBG(FM_NTC | MAIN, "start timer fail!!!\n");
+       }
+
+out:
+    FM_UNLOCK(fm_ops_lock);
+    return ret;
+}
+
+/*
+ *  fm_powerup_tx
+ */
+fm_s32 fm_powerup_tx(struct fm *fm, struct fm_tune_parm *parm)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(fm_low_ops.bi.pwron);
+    FMR_ASSERT(fm_low_ops.bi.pwrupseq_tx);
+
+    if (FM_PWR_TX_ON == fm_pwr_state_get(fm)) {
+        WCN_DBG(FM_NTC | MAIN, "already pwron!\n");
+        parm->err = FM_BADSTATUS;
+        goto out;
+    }
+       else if(FM_PWR_RX_ON == fm_pwr_state_get(fm))
+       {
+        //if Rx is on, we need pwr down  first
+        ret = fm_powerdown(fm);
+        if(ret)
+               {
+           WCN_DBG(FM_ERR | MAIN,"FM pwr down Rx fail!\n"); 
+                  goto out;
+        }
+    }
+
+    if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+
+    //for normal case
+    if (fm->chipon == fm_false) {
+        fm_low_ops.bi.pwron(0);
+        fm->chipon = fm_true;
+    }
+    
+    fm_pwr_state_set(fm, FM_PWR_TX_ON);
+       ret = fm_low_ops.bi.pwrupseq_tx();
+
+       if(ret)
+       {
+               parm->err = FM_FAILED; 
+       }
+       else
+       {
+               parm->err = FM_SUCCESS; 
+       }
+    fm_cur_freq_set(parm->freq);
+       //if(fm_low_ops.ri.rds_bci_get)
+       {
+               fm_timer_sys->count = 0;
+               fm_timer_sys->tx_pwr_ctrl_en = FM_TX_PWR_CTRL_ENABLE;
+               fm_timer_sys->tx_rtc_ctrl_en = FM_TX_RTC_CTRL_ENABLE;
+               fm_timer_sys->tx_desense_en = FM_TX_DESENSE_ENABLE;
+       
+               fm_timer_sys->init(fm_timer_sys, fmtx_timer_func, (unsigned long)g_fm_struct,FM_TIMER_TIMEOUT_MIN, 0);
+               fm_timer_sys->start(fm_timer_sys);
+               WCN_DBG(FM_NTC | MAIN, "start timer ok\n");
+       }
+
+out:
+    FM_UNLOCK(fm_ops_lock);
+    return ret;
+}
+
+static fm_s32 pwrdown_flow(struct fm *fm)
+{
+    fm_s32 ret = 0;
+    FMR_ASSERT(fm_low_ops.ri.rds_onoff);
+    FMR_ASSERT(fm_low_ops.bi.pwrdownseq);
+    FMR_ASSERT(fm_low_ops.bi.low_pwr_wa);
+    if (FM_PWR_OFF == fm_pwr_state_get(fm)) {
+        WCN_DBG(FM_NTC | MAIN, "already pwroff!\n");
+        goto out;
+    }
+       /*if(fm_low_ops.ri.rds_bci_get)
+       {
+               fm_timer_sys->stop(fm_timer_sys);
+               WCN_DBG(FM_NTC | MAIN, "stop timer ok\n");
+       }
+       else
+       {
+               WCN_DBG(FM_NTC | MAIN, "stop timer fail!!!\n");
+       }*/
+    
+    //Disable all interrupt
+    fm_disable_rds_BlerCheck();
+    fm_low_ops.ri.rds_onoff(fm->pstRDSData, fm_false);
+    fm_disable_eint();
+
+    fm_pwr_state_set(fm, FM_PWR_OFF);
+
+    //execute power down sequence
+    ret = fm_low_ops.bi.pwrdownseq();
+
+    fm_low_ops.bi.low_pwr_wa(0);
+    WCN_DBG(FM_ALT | MAIN, "pwrdown_flow exit\n");
+
+out:
+    return ret;
+}
+
+fm_s32 fm_powerdown(struct fm *fm)
+{
+    fm_s32 ret = 0;
+       if (FM_PWR_TX_ON == fm_pwr_state_get(fm))
+       {
+           ret = fm_powerdowntx(fm);
+       }
+       else
+       {
+           if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+           if (FM_LOCK(fm_rxtx_lock)) return(-FM_ELOCK);
+
+           ret = pwrdown_flow(fm);
+
+           FM_UNLOCK(fm_rxtx_lock);
+           FM_UNLOCK(fm_ops_lock);
+    }
+    return ret;
+}
+
+fm_s32 fm_powerdowntx(struct fm *fm)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(fm_low_ops.bi.pwrdownseq_tx);
+    if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+    if (FM_LOCK(fm_rxtx_lock)) return (-FM_ELOCK);
+
+    if (FM_PWR_TX_ON == fm_pwr_state_get(fm)) 
+    {
+               if (FM_LOCK(fm_timer_lock)) return (-FM_ELOCK);
+               fm_timer_sys->stop(fm_timer_sys);
+               FM_UNLOCK(fm_timer_lock);
+               fm_timer_sys->count = 0;
+               fm_timer_sys->tx_pwr_ctrl_en = FM_TX_PWR_CTRL_DISABLE;
+               fm_timer_sys->tx_rtc_ctrl_en = FM_TX_RTC_CTRL_DISABLE;
+               fm_timer_sys->tx_desense_en = FM_TX_DESENSE_DISABLE;
+               
+               fm_low_ops.ri.rds_onoff(fm->pstRDSData, fm_false);
+               //execute power down sequence
+               ret = fm_low_ops.bi.pwrdownseq();
+               if(ret)
+               {
+                       WCN_DBG(FM_ERR | MAIN, "pwrdown tx 1 fail\n");
+               }
+               else
+               {
+                       ret = fm_low_ops.bi.pwrdownseq_tx();
+                       if(ret)
+                       {
+                               WCN_DBG(FM_ERR | MAIN, "pwrdown tx 2 fail\n");
+                       }
+               }
+               fm_pwr_state_set(fm, FM_PWR_OFF);
+               WCN_DBG(FM_NTC | MAIN, "pwrdown tx ok\n");
+    }
+
+    FM_UNLOCK(fm_rxtx_lock);
+    FM_UNLOCK(fm_ops_lock);
+    return ret;
+}
+
+fm_s32 fm_seek(struct fm *fm, struct fm_seek_parm *parm)
+{
+    fm_s32 ret = 0;
+    fm_u16 seekdir, space;
+
+    FMR_ASSERT(fm_low_ops.bi.seek);
+    if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+
+    if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) {
+        parm->err = FM_BADSTATUS;
+        ret = -EPERM;
+        goto out;
+    }
+
+    if (parm->space == FM_SPACE_100K) {
+        space = 0x0002;
+    } else if (parm->space == FM_SPACE_50K) {
+        space = 0x0001;
+    } else if (parm->space == FM_SPACE_200K) {
+        space = 0x0004;
+    } else {
+        //default
+        space = 0x0002;
+    }
+
+    if (parm->band == FM_BAND_UE) {
+        fm->min_freq = FM_UE_FREQ_MIN;
+        fm->max_freq = FM_UE_FREQ_MAX;
+    } else if (parm->band == FM_BAND_JAPANW) {
+        fm->min_freq = FM_JP_FREQ_MIN;
+        fm->max_freq = FM_JP_FREQ_MAX;
+    } else if (parm->band == FM_BAND_SPECIAL) {
+        fm->min_freq = FM_RX_BAND_FREQ_L;
+        fm->max_freq = FM_RX_BAND_FREQ_H;
+    } else {
+        WCN_DBG(FM_ALT | MAIN, "band:%d out of range\n", parm->band);
+        parm->err = FM_EPARM;
+        ret = -EPERM;
+        goto out;
+    }
+
+    if (parm->freq < fm->min_freq || parm->freq > fm->max_freq) {
+        WCN_DBG(FM_ALT | MAIN, "freq:%d out of range\n", parm->freq);
+        parm->err = FM_EPARM;
+        ret = -EPERM;
+        goto out;
+    }
+
+    if (parm->seekdir == FM_SEEK_UP) {
+        seekdir = FM_SEEK_UP;
+    } else {
+        seekdir = FM_SEEK_DOWN;
+    }
+
+    fm_op_state_set(fm, FM_STA_SEEK);
+
+    // seek successfully
+    if (fm_true == fm_low_ops.bi.seek(fm->min_freq, fm->max_freq, &(parm->freq), seekdir, space)) {
+        parm->err = FM_SUCCESS;
+    } else {
+        parm->err = FM_SEEK_FAILED;
+        ret = -EPERM;
+    }
+
+    if ((parm->space != FM_SPACE_50K) && (1 == fm_get_channel_space(parm->freq))) 
+    {
+        parm->freq /= 10; //(8750 / 10) = 875
+    }
+
+    fm_op_state_set(fm, FM_STA_PLAY);
+out:
+    FM_UNLOCK(fm_ops_lock);
+    return ret;
+}
+
+/***********************************************************
+Function:      fm_tx_scan()
+
+Description:   get the valid channels for fm tx function
+
+Para:          fm--->fm driver global info
+                       parm--->input/output paramater
+                       
+Return:                0, if success; error code, if failed
+***********************************************************/
+fm_s32 fm_tx_scan(struct fm *fm, struct fm_tx_scan_parm *parm)
+{
+    fm_s32 ret = 0;
+       fm_u16 scandir = 0;
+       fm_u16 space = FM_SPACE_100K;
+       FMR_ASSERT(fm_low_ops.bi.tx_scan);
+
+       if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+
+       if (fm->chipon != fm_true) 
+       {
+               parm->err = FM_BADSTATUS;
+               ret=-EPERM;
+               WCN_DBG(FM_ERR | MAIN, "tx scan chip not on\n");
+               goto out;
+       }
+       switch(parm->scandir){
+               case FM_TX_SCAN_UP:
+                       scandir = 0;
+                       break;
+               case FM_TX_SCAN_DOWN:
+                       scandir = 1;
+                       break;
+               default:
+                       scandir = 0;
+                       break;
+       }
+       
+       /*if (parm->space == FM_SPACE_100K) {
+        space = 2;
+    } else if (parm->space == FM_SPACE_50K) {
+        space = 1;
+    } else if (parm->space == FM_SPACE_200K) {
+        space = 4;
+    } else {
+        //default
+        space = 2;
+       }*/
+       
+    if (parm->band == FM_BAND_UE) {
+        fm->min_freq = FM_UE_FREQ_MIN;
+        fm->max_freq = FM_UE_FREQ_MAX;
+    } else if (parm->band == FM_BAND_JAPANW) {
+        fm->min_freq = FM_JP_FREQ_MIN;
+        fm->max_freq = FM_JP_FREQ_MAX;
+    } else if (parm->band == FM_BAND_SPECIAL) {
+        fm->min_freq = FM_FREQ_MIN;
+        fm->max_freq = FM_FREQ_MAX;
+    } else 
+    {
+        WCN_DBG(FM_ERR| MAIN,"band:%d out of range\n", parm->band);
+               parm->err = FM_EPARM;
+               ret=-EPERM;
+               goto out;
+       }
+
+    if (unlikely((parm->freq < fm->min_freq) || (parm->freq > fm->max_freq))){
+        parm->err = FM_EPARM;
+        ret=-EPERM;
+        goto out;
+    }
+
+       if (unlikely(parm->ScanTBLSize < TX_SCAN_MIN || parm->ScanTBLSize > TX_SCAN_MAX)){
+        parm->err = FM_EPARM;
+        ret=-EPERM;
+        goto out;
+    }
+
+    ret = fm_low_ops.bi.anaswitch(FM_ANA_SHORT);
+    if(ret){
+        WCN_DBG(FM_ERR | MAIN,"switch to short ana failed\n");
+        goto out;
+    }
+    
+       //do tx scan
+       if(!(ret = fm_low_ops.bi.tx_scan(fm->min_freq, fm->max_freq, &(parm->freq), 
+                                                               parm->ScanTBL, &(parm->ScanTBLSize), scandir, space))){
+        parm->err = FM_SUCCESS;
+    }else{
+        WCN_DBG(FM_ERR | MAIN,"fm_tx_scan failed\n");
+        parm->err = FM_SCAN_FAILED;
+    }
+out:    
+       FM_UNLOCK(fm_ops_lock);
+    return ret;
+}
+
+fm_s32  fm_scan(struct fm *fm, struct fm_scan_parm *parm)
+{
+    fm_s32 ret = 0;
+    fm_u16 scandir = FM_SEEK_UP, space;
+
+    FMR_ASSERT(fm_low_ops.bi.scan);
+       WCN_DBG(FM_NTC | MAIN, "fm_scan:start\n");
+    if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+
+    if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) {
+        parm->err = FM_BADSTATUS;
+        ret = -EPERM;
+        goto out;
+    }
+
+    if (parm->space == FM_SPACE_100K) {
+        space = 0x0002;
+    } else if (parm->space == FM_SPACE_50K) {
+        space = 0x0001;
+    } else if (parm->space == FM_SPACE_200K) {
+        space = 0x0004;
+    } else {
+        //default
+        space = 0x0002;
+    }
+
+    if (parm->band == FM_BAND_UE) {
+        fm->min_freq = FM_UE_FREQ_MIN;
+        fm->max_freq = FM_UE_FREQ_MAX;
+    } else if (parm->band == FM_BAND_JAPANW) {
+        fm->min_freq = FM_JP_FREQ_MIN;
+        fm->max_freq = FM_JP_FREQ_MAX;
+    } else if (parm->band == FM_BAND_SPECIAL) {
+        fm->min_freq = FM_RX_BAND_FREQ_L;
+        fm->max_freq = FM_RX_BAND_FREQ_H;
+    } else {
+        WCN_DBG(FM_ALT | MAIN, "band:%d out of range\n", parm->band);
+        parm->err = FM_EPARM;
+        ret = -EPERM;
+        goto out;
+    }
+
+    fm_op_state_set(fm, FM_STA_SCAN);
+    scan_stop_flag = fm_false;
+
+    if (fm_true == fm_low_ops.bi.scan(fm->min_freq, fm->max_freq, &(parm->freq), parm->ScanTBL, &(parm->ScanTBLSize), scandir, space)) {
+        parm->err = FM_SUCCESS;
+    } else {
+        WCN_DBG(FM_ALT | MAIN, "fm_scan failed\n");
+        parm->err = FM_SEEK_FAILED;
+        ret = -EPERM;
+    }
+
+    fm_op_state_set(fm, FM_STA_STOP);
+
+out:
+    FM_UNLOCK(fm_ops_lock);
+       WCN_DBG(FM_NTC | MAIN, "fm_scan:done\n");
+    return ret;
+}
+
+
+#define SCAN_SEG_LEN 250
+static struct fm_cqi cqi_buf[SCAN_SEG_LEN];
+
+fm_s32 fm_scan_new(struct fm *fm, struct fm_scan_t *parm)
+{
+    fm_s32 ret = 0;
+    fm_s32 tmp;
+    fm_s32 cnt, seg;
+    fm_s32 i, j;
+    fm_s32 start_freq, end_freq;
+    fm_u16 scan_tbl[FM_SCANTBL_SIZE]; //need no less than the chip
+    fm_u16 tbl_size = FM_SCANTBL_SIZE;
+    fm_u16 tmp_freq = 0;
+    fm_s32 chl_cnt;
+    fm_s32 ch_offset, step, tmp_val;
+    fm_u16 space_idx = 0x0002;
+    
+    fm_s32 cqi_cnt, cqi_idx;
+    fm_s8 *buf = (fm_s8*)cqi_buf;
+    
+    FMR_ASSERT(fm_low_ops.bi.scan);
+    FMR_ASSERT(fm_low_ops.bi.cqi_get);
+    if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+
+    // caculate channel number, get segment count
+    cnt = (parm->upper - parm->lower) / parm->space + 1; //Eg, (10800 - 8750) / 5 = 411
+    seg = (cnt / SCAN_SEG_LEN) + ((cnt % SCAN_SEG_LEN) ? 1 : 0); //Eg, (411 / 200) + ((411 % 200) ? 1 : 0) = 2 + 1 = 3
+
+    WCN_DBG(FM_NTC | MAIN, "total ch %d, seg %d\n", cnt, seg);
+
+    // alloc memory
+    tmp = cnt * sizeof(struct fm_ch_rssi*);
+    if (parm->sr_size < tmp) {
+        if (parm->sr.ch_rssi_buf) {
+            fm_free(parm->sr.ch_rssi_buf);
+            parm->sr.ch_rssi_buf = NULL;
+        }
+        parm->sr_size = tmp;                
+    }
+    
+    if (!parm->sr.ch_rssi_buf) {
+        parm->sr.ch_rssi_buf = (struct fm_ch_rssi*)fm_zalloc(parm->sr_size);
+        if (!parm->sr.ch_rssi_buf) {
+            WCN_DBG(FM_ERR | MAIN, "scan alloc mem failed\n");
+            parm->sr_size = 0;
+            return -2;
+        }
+    }
+    
+    if (parm->space == 5) {
+        space_idx = 0x0001; // 50Khz
+    } else if (parm->space == 10) {
+        space_idx = 0x0002; // 100Khz
+    } else if (parm->space == 20) {
+        space_idx = 0x0004; // 200Khz
+    } 
+
+    
+    fm_op_state_set(fm, FM_STA_SCAN);
+    
+    // do scan
+    chl_cnt = 0;
+    for (i = 0; (i < seg) && (fm_false == scan_stop_flag); i++) {
+        cqi_cnt = 0;
+        cqi_idx = 0;
+        
+        start_freq = parm->lower + SCAN_SEG_LEN * parm->space * i;
+        end_freq = parm->lower + SCAN_SEG_LEN * parm->space * (i + 1) - parm->space;
+        end_freq = (end_freq > parm->upper) ? parm->upper : end_freq;
+
+        WCN_DBG(FM_NTC | MAIN, "seg %d, start %d, end %d\n", i, start_freq, end_freq);
+        if(fm_false == fm_low_ops.bi.scan(start_freq, end_freq, &tmp_freq, scan_tbl, &tbl_size, FM_SEEK_UP, space_idx)) {
+            ret = -1;
+            goto out;
+        }
+
+        // get channel count
+        for (ch_offset = 0; ch_offset < FM_SCANTBL_SIZE; ch_offset++) {
+                   if (scan_tbl[ch_offset] == 0)
+                           continue;
+                   for (step = 0; step < 16; step++) {
+                           if (scan_tbl[ch_offset] & (1 << step)) {
+                    tmp_val =  start_freq + (ch_offset * 16 + step) * parm->space;
+                    if (tmp_val <= end_freq) {
+                        // record valid  result channel
+                        WCN_DBG(FM_NTC | MAIN, "freq %d\n", tmp_val);
+                        parm->sr.ch_rssi_buf[chl_cnt].freq = tmp_val;
+                        chl_cnt++; 
+                        cqi_cnt++;
+                    }
+                           }
+                   }
+           }  
+
+        // get cqi
+        if(fm_low_ops.bi.cqi_get)
+        {
+               tmp = cqi_cnt;
+               while ((cqi_cnt > 0) && (fm_false == scan_stop_flag)) {
+                   ret = fm_low_ops.bi.cqi_get(buf + (16 * sizeof(struct fm_cqi) * cqi_idx), 
+                       sizeof(cqi_buf) - (16 * sizeof(struct fm_cqi) * cqi_idx));
+                   if (ret) {
+                       goto out;
+                   }
+
+                   cqi_cnt -= 16;
+                   cqi_idx++;
+               }
+               cqi_cnt = tmp;
+
+               // fill cqi to result buffer
+               for (j = 0; j < cqi_cnt; j++) {
+                   tmp = chl_cnt - cqi_cnt + j; // target pos
+                   parm->sr.ch_rssi_buf[tmp].freq = (fm_u16)cqi_buf[j].ch;
+                   parm->sr.ch_rssi_buf[tmp].rssi= cqi_buf[j].rssi;
+                   WCN_DBG(FM_NTC | MAIN, "idx %d, freq %d, rssi %d \n", tmp, parm->sr.ch_rssi_buf[tmp].freq, parm->sr.ch_rssi_buf[tmp].rssi);
+               }
+        }
+        //6620 won't get rssi in scan new
+        //else if(fm_low_ops.bi.rssiget)
+    }
+     
+    fm_op_state_set(fm, FM_STA_STOP);
+    
+out:
+    scan_stop_flag = fm_false;
+    FM_UNLOCK(fm_ops_lock);
+    parm->num = chl_cnt;
+    return ret;
+}
+
+
+fm_s32 fm_seek_new(struct fm *fm, struct fm_seek_t *parm)
+{
+    fm_s32 ret = 0;
+    fm_s32 space_idx = 0x0002;
+
+    FMR_ASSERT(fm_low_ops.bi.setfreq);
+    FMR_ASSERT(fm_low_ops.bi.rssiget);
+    FMR_ASSERT(fm_low_ops.bi.rampdown);
+
+    if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+     
+    if (parm->freq < parm->lower || parm->freq > parm->upper) {
+        WCN_DBG(FM_ERR | MAIN, "seek start freq:%d out of range\n", parm->freq);
+        ret = -EPERM;
+        goto out;
+    }
+
+    // tune to start freq
+    fm_low_ops.bi.rampdown();
+    fm_low_ops.bi.setfreq(parm->freq);
+
+    if (parm->space == 5) {
+        space_idx = 0x0001;
+    } else if (parm->space == 10) {
+        space_idx = 0x0002;
+    } else if (parm->space == 20) {
+        space_idx = 0x0004;
+    }
+    
+    fm_op_state_set(fm, FM_STA_SEEK);
+    if (fm_false == fm_low_ops.bi.seek(parm->lower, parm->upper, &(parm->freq), parm->dir, space_idx)) {
+        ret = -1;
+        goto out;
+    } 
+
+    // tune to new channel
+    fm_low_ops.bi.setfreq(parm->freq);
+    fm_low_ops.bi.rssiget(&parm->th);
+    
+out:
+    FM_UNLOCK(fm_ops_lock);
+    return ret;    
+}
+
+
+fm_s32 fm_tune_new(struct fm *fm, struct fm_tune_t *parm)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(fm_low_ops.bi.mute);
+    FMR_ASSERT(fm_low_ops.bi.rampdown);
+    FMR_ASSERT(fm_low_ops.bi.setfreq);
+
+    if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+
+    WCN_DBG(FM_DBG | MAIN, "%s\n", __func__);
+
+    if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) {
+        ret = -EPERM;
+        goto out;
+    }
+
+    if (parm->freq < parm->lower || parm->freq > parm->upper) {
+        WCN_DBG(FM_ERR | MAIN, "tune freq:%d out of range\n", parm->freq);
+        ret = -EPERM;
+        goto out;
+    }
+    
+//    fm_low_ops.bi.mute(fm_true);
+    fm_low_ops.bi.rampdown();
+
+    if (fm_cur_freq_get() != parm->freq) {
+        fm_memset(fm->pstRDSData, 0, sizeof(rds_t));
+    }
+
+#if 0//(!defined(MT6620_FM)&&!defined(MT6628_FM))
+    //HILO side adjust if need
+    if (priv_adv.priv_tbl.hl_dese) {
+        if ((ret = priv_adv.priv_tbl.hl_dese(parm->freq, NULL)) < 0) {
+            goto out;
+        }
+
+        WCN_DBG(FM_INF | MAIN, "HILO side %d\n", ret);
+    }
+
+    //Frequency avoid adjust if need
+    if (priv_adv.priv_tbl.fa_dese) {
+        if ((ret = priv_adv.priv_tbl.fa_dese(parm->freq, NULL)) < 0) {
+            goto out;
+        }
+
+        WCN_DBG(FM_INF | MAIN, "FA %d\n", ret);
+    }
+
+    //MCU clock adjust if need
+    if (priv_adv.priv_tbl.mcu_dese) {
+        if ((ret = priv_adv.priv_tbl.mcu_dese(parm->freq, NULL)) < 0) {
+            goto out;
+        }
+
+        WCN_DBG(FM_INF | MAIN, "MCU %d\n", ret);
+    }
+
+    //GPS clock adjust if need
+    if (priv_adv.priv_tbl.gps_dese) {
+        if ((ret = priv_adv.priv_tbl.gps_dese(parm->freq, NULL)) < 0) {
+            goto out;
+        }
+
+        WCN_DBG(FM_INF | MAIN, "GPS %d\n", ret);
+    }
+#endif
+    fm_op_state_set(fm, FM_STA_TUNE);
+    WCN_DBG(FM_ALT | MAIN, "tuning to %d\n", parm->freq);
+
+    if (fm_false == fm_low_ops.bi.setfreq(parm->freq)) {
+        WCN_DBG(FM_ALT | MAIN, "FM tune failed\n");
+        ret = -EPERM;
+        goto out;
+    }
+
+//    fm_low_ops.bi.mute(fm_false);
+    fm_op_state_set(fm, FM_STA_PLAY);
+out:
+    FM_UNLOCK(fm_ops_lock);
+    return ret;
+}
+
+
+fm_s32  fm_cqi_get(struct fm *fm, fm_s32 ch_num, fm_s8 *buf, fm_s32 buf_size)
+{
+    fm_s32 ret = 0;
+    fm_s32 idx = 0;
+
+    FMR_ASSERT(fm_low_ops.bi.cqi_get);
+    if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+
+    if (fm_true == scan_stop_flag) {
+        WCN_DBG(FM_NTC | MAIN, "scan flow aborted, do not get CQI\n");
+        ret = -1;
+        goto out;
+    }
+    
+    if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) {
+        ret = -EPERM;
+        goto out;
+    }
+
+    if (ch_num*sizeof(struct fm_cqi) > buf_size) {
+        ret = -EPERM;
+        goto out;
+    }
+
+    fm_op_state_set(fm, FM_STA_SCAN);
+
+    idx = 0;
+    WCN_DBG(FM_NTC | MAIN, "cqi num %d\n", ch_num);
+
+    while (ch_num > 0) {
+        ret = fm_low_ops.bi.cqi_get(buf + 16 * sizeof(struct fm_cqi) * idx, buf_size - 16 * sizeof(struct fm_cqi) * idx);
+
+        if (ret) {
+            goto out;
+        }
+
+        ch_num -= 16;
+        idx++;
+    }
+
+    fm_op_state_set(fm, FM_STA_STOP);
+
+out:
+    FM_UNLOCK(fm_ops_lock);
+    return ret;
+}
+
+
+/*  fm_is_dese_chan -- check if gived channel is a de-sense channel or not
+  *  @pfm - fm driver global DS
+  *  @freq - gived channel
+  *  return value: 0, not a dese chan; 1, a dese chan; else error NO.
+  */
+fm_s32 fm_is_dese_chan(struct fm *pfm, fm_u16 freq)
+{
+    fm_s32 ret = 0;
+    FMR_ASSERT(pfm);
+       if (fm_low_ops.bi.is_dese_chan) 
+       {
+        if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+               ret = fm_low_ops.bi.is_dese_chan(freq);
+        FM_UNLOCK(fm_ops_lock);
+       }
+
+       return ret;
+}
+
+
+/*  fm_is_dese_chan -- check if gived channel is a de-sense channel or not
+  *  @pfm - fm driver global DS
+  *  @freq - gived channel
+  *  return value: 0, not a dese chan; 1, a dese chan; else error NO.
+  */
+fm_s32 fm_desense_check(struct fm *pfm, fm_u16 freq,fm_s32 rssi)
+{
+    fm_s32 ret = 0;
+    FMR_ASSERT(pfm);
+    if (fm_low_ops.bi.desense_check) 
+       {
+        if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+        ret = fm_low_ops.bi.desense_check(freq,rssi);
+        FM_UNLOCK(fm_ops_lock);
+    }
+
+    return ret;
+}
+fm_s32 fm_dump_reg(void)
+{
+    fm_s32 ret = 0;
+    if (fm_low_ops.bi.dumpreg) 
+    {
+           if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+        ret = fm_low_ops.bi.dumpreg();
+           FM_UNLOCK(fm_ops_lock);
+    }
+    return ret;
+}
+
+/*  fm_get_hw_info -- hw info: chip id, ECO version, DSP ROM version, Patch version
+  *  @pfm - fm driver global DS
+  *  @freq - target buffer
+  *  return value: 0, success; else error NO.
+  */
+fm_s32 fm_get_hw_info(struct fm *pfm, struct fm_hw_info *req)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(req);
+
+    //default value for all chips
+    req->chip_id = 0x000066FF;
+    req->eco_ver = 0x00000000;
+    req->rom_ver = 0x00000001;
+    req->patch_ver = 0x00000100;
+    req->reserve = 0x00000000;
+
+    //get actual chip hw info
+    if (fm_low_ops.bi.hwinfo_get) {
+        if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+        ret = fm_low_ops.bi.hwinfo_get(req);
+        FM_UNLOCK(fm_ops_lock);
+    }
+
+    return ret;
+}
+
+
+/*  fm_get_i2s_info -- i2s info: on/off, master/slave, sample rate
+  *  @pfm - fm driver global DS
+  *  @freq - target buffer
+  *  return value: 0, success; else error NO.
+  */
+fm_s32 fm_get_i2s_info(struct fm *pfm, struct fm_i2s_info *req)
+{
+    FMR_ASSERT(req);
+
+    if (fm_low_ops.bi.i2s_get) {
+        return fm_low_ops.bi.i2s_get(&req->status, &req->mode, &req->rate);
+    } else {
+        req->status = fm_i2s_inf.status;
+        req->mode = fm_i2s_inf.mode;
+        req->rate = fm_i2s_inf.rate;
+
+        return 0;
+    }
+}
+
+
+fm_s32  fm_hwscan_stop(struct fm *fm)
+{
+    fm_s32 ret = 0;
+
+    if ((FM_STA_SCAN != fm_op_state_get(fm))&&(FM_STA_SEEK!=fm_op_state_get(fm))) 
+       {
+        WCN_DBG(FM_WAR | MAIN, "fm isn't on scan, no need stop\n");
+        return ret;
+    }
+
+    FMR_ASSERT(fm_low_ops.bi.scanstop);
+
+    fm_low_ops.bi.scanstop();
+    fm_low_ops.bi.seekstop();
+    scan_stop_flag = fm_true;
+    WCN_DBG(FM_DBG | MAIN, "fm will stop scan\n");
+
+    if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+    
+    fm_low_ops.bi.rampdown();
+    fm_low_ops.bi.setfreq(fm_cur_freq_get());
+
+    FM_UNLOCK(fm_ops_lock);
+    
+    return ret;
+}
+
+/* fm_ana_switch -- switch antenna to long/short
+ * @fm - fm driver main data structure
+ * @antenna - 0, long; 1, short
+ * If success, return 0; else error code
+ */
+fm_s32 fm_ana_switch(struct fm *fm, fm_s32 antenna)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(fm_low_ops.bi.anaswitch);
+    if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+
+    WCN_DBG(FM_DBG | MAIN, "Switching ana to %s\n", antenna ? "short" : "long");
+    fm->ana_type = antenna;
+    ret = fm_low_ops.bi.anaswitch(antenna);
+
+    if (ret) {
+        WCN_DBG(FM_ALT | MAIN, "Switch ana Failed\n");
+    } else {
+        WCN_DBG(FM_DBG | MAIN, "Switch ana OK!\n");
+    }
+
+    FM_UNLOCK(fm_ops_lock);
+    return ret;
+}
+
+//volume?[0~15]
+fm_s32 fm_setvol(struct fm *fm, fm_u32 vol)
+{
+    fm_u8 tmp_vol;
+
+    if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) {
+               return -EPERM;
+    }
+    FMR_ASSERT(fm_low_ops.bi.volset);
+    if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+
+    tmp_vol = (vol > 15) ? 15 : vol;
+    fm_low_ops.bi.volset(tmp_vol);
+    fm->vol = (fm_s32)tmp_vol;
+
+    FM_UNLOCK(fm_ops_lock);
+    return 0;
+}
+
+fm_s32 fm_getvol(struct fm *fm, fm_u32 *vol)
+{
+    fm_u8 tmp_vol;
+
+    if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) {
+               return -EPERM;
+    }
+    FMR_ASSERT(fm_low_ops.bi.volget);
+    if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+
+    fm_low_ops.bi.volget(&tmp_vol);
+    *vol = (fm_u32)tmp_vol;
+
+    FM_UNLOCK(fm_ops_lock);
+    return 0;
+}
+
+fm_s32 fm_mute(struct fm *fm, fm_u32 bmute)
+{
+    fm_s32 ret = 0;
+
+    if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) {
+        ret = -EPERM;
+               return ret;
+    }
+    FMR_ASSERT(fm_low_ops.bi.mute);
+    if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+
+    if (bmute) {
+        ret = fm_low_ops.bi.mute(fm_true);
+        fm->mute = fm_true;
+    } else {
+        ret = fm_low_ops.bi.mute(fm_false);
+        fm->mute = fm_false;
+    }
+
+    FM_UNLOCK(fm_ops_lock);
+    return ret;
+}
+
+fm_s32 fm_getrssi(struct fm *fm, fm_s32 *rssi)
+{
+    fm_s32 ret = 0;
+
+    if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) {
+        ret = -EPERM;
+               return ret;
+    }
+    FMR_ASSERT(fm_low_ops.bi.rssiget);
+    if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+
+    ret = fm_low_ops.bi.rssiget(rssi);
+
+    FM_UNLOCK(fm_ops_lock);
+    return ret;
+}
+
+fm_s32 fm_reg_read(struct fm *fm, fm_u8 addr, fm_u16 *val)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(fm_low_ops.bi.read);
+    if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+
+    ret = fm_low_ops.bi.read(addr, val);
+
+    FM_UNLOCK(fm_ops_lock);
+    return ret;
+}
+
+fm_s32 fm_reg_write(struct fm *fm, fm_u8 addr, fm_u16 val)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(fm_low_ops.bi.write);
+    if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+
+    ret = fm_low_ops.bi.write(addr, val);
+
+    FM_UNLOCK(fm_ops_lock);
+    return ret;
+}
+
+fm_s32 fm_chipid_get(struct fm *fm, fm_u16 *chipid)
+{
+    FMR_ASSERT(chipid);
+    if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+
+    *chipid = fm->chip_id;
+
+    FM_UNLOCK(fm_ops_lock);
+    return 0;
+}
+
+fm_s32 fm_monostereo_get(struct fm *fm, fm_u16 *ms)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(fm_low_ops.bi.msget);
+    FMR_ASSERT(ms);
+    if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+
+    if (fm_low_ops.bi.msget(ms) == fm_false) {
+        ret = -FM_EPARA;
+    }
+
+    FM_UNLOCK(fm_ops_lock);
+    return ret;
+}
+
+/*
+ * Force set to stero/mono mode
+ * @MonoStereo -- 0, auto; 1, mono
+ * If success, return 0; else error code
+ */
+fm_s32 fm_monostereo_set(struct fm *fm, fm_s32 ms)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(fm_low_ops.bi.msset);
+    if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+
+    ret = fm_low_ops.bi.msset(ms);
+
+    FM_UNLOCK(fm_ops_lock);
+    return ret;
+}
+
+fm_s32 fm_pamd_get(struct fm *fm, fm_u16 *pamd)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(fm_low_ops.bi.pamdget);
+    FMR_ASSERT(pamd);
+    if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+
+    if (fm_low_ops.bi.pamdget(pamd) == fm_false) {
+        ret = -FM_EPARA;
+    }
+
+    FM_UNLOCK(fm_ops_lock);
+    return ret;
+}
+
+fm_s32 fm_caparray_get(struct fm *fm, fm_s32 *ca)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(fm_low_ops.bi.caparray_get);
+    FMR_ASSERT(ca);
+    if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+
+    ret = fm_low_ops.bi.caparray_get(ca);
+
+    FM_UNLOCK(fm_ops_lock);
+    return ret;
+}
+
+fm_s32 fm_em_test(struct fm *fm, fm_u16 group, fm_u16 item, fm_u32 val)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(fm_low_ops.bi.em);
+    if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+
+    if (fm_false == fm_low_ops.bi.em(group, item, val)) {
+        ret = -FM_EPARA;
+    }
+
+    FM_UNLOCK(fm_ops_lock);
+    return ret;
+}
+
+fm_s32 fm_rds_tx(struct fm *fm, struct fm_rds_tx_parm *parm)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(fm_low_ops.ri.rds_tx);
+    FMR_ASSERT(fm_low_ops.ri.rds_tx_enable);
+
+    if (fm_pwr_state_get(fm) != FM_PWR_TX_ON) {
+        parm->err = FM_BADSTATUS;
+        ret = -FM_EPARA;
+        goto out;
+    }
+    if(parm->other_rds_cnt > 29)
+    {
+        parm->err = FM_EPARM;
+        WCN_DBG(FM_ERR | MAIN,"other_rds_cnt=%d\n",parm->other_rds_cnt);
+        ret = -FM_EPARA;
+        goto out;
+    }
+    
+    ret = fm_low_ops.ri.rds_tx_enable();
+    if(ret){
+        WCN_DBG(FM_ERR | MAIN,"Rds_Tx_Enable failed!\n");
+        goto out;
+    }   
+    fm->rdstx_on = fm_true;
+    ret = fm_low_ops.ri.rds_tx(parm->pi, parm->ps, parm->other_rds, parm->other_rds_cnt);
+    if(ret){
+        WCN_DBG(FM_ERR | MAIN,"Rds_Tx failed!\n");
+        goto out;
+    }   
+//    fm_cxt->txcxt.rdsTxOn = true;
+//    fm_cxt->txcxt.pi = parm->pi;
+//    memcpy(fm_cxt->txcxt.ps, parm->ps,sizeof(parm->ps));
+//    memcpy(fm_cxt->txcxt.other_rds, parm->other_rds,sizeof(parm->other_rds));
+//    fm_cxt->txcxt.other_rds_cnt = parm->other_rds_cnt; 
+out:
+    return ret;
+}
+
+fm_s32 fm_rds_onoff(struct fm *fm, fm_u16 rdson_off)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(fm_low_ops.ri.rds_onoff);
+    if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+
+    if (rdson_off) {
+        fm->rds_on = fm_true;
+        if (fm_low_ops.ri.rds_onoff(fm->pstRDSData, fm_true) == fm_false) {
+            WCN_DBG(FM_ALT | MAIN, "FM_IOCTL_RDS_ONOFF faield\n");
+            ret = -EPERM;
+            goto out;
+        }
+
+        fm_enable_rds_BlerCheck(fm);
+    } else {
+        fm->rds_on = fm_false;
+        fm_disable_rds_BlerCheck();
+        fm_low_ops.ri.rds_onoff(fm->pstRDSData, fm_false);
+    }
+
+out:
+    FM_UNLOCK(fm_ops_lock);
+    return ret;
+}
+
+fm_s32 fm_rds_good_bc_get(struct fm *fm, fm_u16 *gbc)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(fm_low_ops.ri.rds_gbc_get);
+    FMR_ASSERT(gbc);
+    if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+
+    *gbc = fm_low_ops.ri.rds_gbc_get();
+
+    FM_UNLOCK(fm_ops_lock);
+    return ret;
+}
+
+fm_s32 fm_rds_bad_bc_get(struct fm *fm, fm_u16 *bbc)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(fm_low_ops.ri.rds_bbc_get);
+    FMR_ASSERT(bbc);
+    if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+
+    *bbc = fm_low_ops.ri.rds_bbc_get();
+
+    FM_UNLOCK(fm_ops_lock);
+    return ret;
+}
+
+fm_s32 fm_rds_bler_ratio_get(struct fm *fm, fm_u16 *bbr)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(fm_low_ops.ri.rds_bbr_get);
+    FMR_ASSERT(bbr);
+    if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+
+    *bbr = (fm_u16)fm_low_ops.ri.rds_bbr_get();
+
+    FM_UNLOCK(fm_ops_lock);
+    return ret;
+}
+
+fm_s32 fm_rds_group_cnt_get(struct fm *fm, struct rds_group_cnt_t *dst)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(fm_low_ops.ri.rds_gc_get);
+    FMR_ASSERT(dst);
+    if (FM_LOCK(fm_rds_cnt)) return (-FM_ELOCK);
+
+    ret = fm_low_ops.ri.rds_gc_get(dst, fm->pstRDSData);
+
+    FM_UNLOCK(fm_rds_cnt);
+    return ret;
+}
+
+fm_s32 fm_rds_group_cnt_reset(struct fm *fm)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(fm_low_ops.ri.rds_gc_reset);
+    if (FM_LOCK(fm_rds_cnt)) return (-FM_ELOCK);
+
+    ret = fm_low_ops.ri.rds_gc_reset(fm->pstRDSData);
+
+    FM_UNLOCK(fm_rds_cnt);
+    return ret;
+}
+
+fm_s32 fm_rds_log_get(struct fm *fm, struct rds_rx_t *dst, fm_s32 *dst_len)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(fm_low_ops.ri.rds_log_get);
+    FMR_ASSERT(dst);
+    FMR_ASSERT(dst_len);
+    if (FM_LOCK(fm_read_lock)) return (-FM_ELOCK);
+
+    ret = fm_low_ops.ri.rds_log_get(dst, dst_len);
+
+    FM_UNLOCK(fm_read_lock);
+    return ret;
+}
+
+fm_s32 fm_rds_block_cnt_reset(struct fm *fm)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(fm_low_ops.ri.rds_bc_reset);
+    if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+
+    ret = fm_low_ops.ri.rds_bc_reset();
+
+    FM_UNLOCK(fm_ops_lock);
+    return ret;
+}
+
+fm_s32 fm_i2s_set(struct fm *fm, fm_s32 onoff, fm_s32 mode, fm_s32 sample)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(fm_low_ops.bi.i2s_set);
+    if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+
+    ret = fm_low_ops.bi.i2s_set(onoff, mode, sample);
+
+    FM_UNLOCK(fm_ops_lock);
+    return ret;
+}
+
+/*
+ *  fm_tune_tx
+ */
+fm_s32 fm_tune_tx(struct fm *fm, struct fm_tune_parm *parm)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(fm_low_ops.bi.tune_tx);
+    
+    if (fm_pwr_state_get(fm) != FM_PWR_TX_ON) {
+        parm->err = FM_BADSTATUS;
+        return -EPERM;
+    }
+    if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+    
+    WCN_DBG(FM_DBG | MAIN, "%s\n", __func__);
+
+       fm_op_state_set(fm, FM_STA_TUNE);
+       WCN_DBG(FM_NTC | MAIN, "Tx tune to %d\n", parm->freq);
+#if 0//ramp down tx will do in tx tune  flow
+    while(0){
+        if((ret = MT6620_RampDown_Tx()))
+            return ret;
+    }
+#endif
+    //tune to desired channel
+    if (fm_true != fm_low_ops.bi.tune_tx(parm->freq)) 
+    {
+        parm->err = FM_TUNE_FAILED;
+        WCN_DBG(FM_ALT | MAIN, "Tx tune failed\n");
+        ret = -EPERM;
+    }
+       fm_op_state_set(fm, FM_STA_PLAY);
+       FM_UNLOCK(fm_ops_lock);
+    
+    return ret;
+}
+
+/*
+ *  fm_tune
+ */
+fm_s32 fm_tune(struct fm *fm, struct fm_tune_parm *parm)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(fm_low_ops.bi.mute);
+    FMR_ASSERT(fm_low_ops.bi.rampdown);
+    FMR_ASSERT(fm_low_ops.bi.setfreq);
+
+    if (FM_LOCK(fm_ops_lock)) return (-FM_ELOCK);
+
+    WCN_DBG(FM_DBG | MAIN, "%s\n", __func__);
+
+    if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) {
+        parm->err = FM_BADSTATUS;
+        ret = -EPERM;
+        goto out;
+    }
+
+//    fm_low_ops.bi.mute(fm_true);
+    fm_low_ops.bi.rampdown();
+
+    if (fm_cur_freq_get() != parm->freq) {
+        fm_memset(fm->pstRDSData, 0, sizeof(rds_t));
+    }
+
+#if 0//(!defined(MT6620_FM)&&!defined(MT6628_FM))
+    //HILO side adjust if need
+    if (priv_adv.priv_tbl.hl_dese) {
+        if ((ret = priv_adv.priv_tbl.hl_dese(parm->freq, NULL)) < 0) {
+            goto out;
+        }
+
+        WCN_DBG(FM_INF | MAIN, "HILO side %d\n", ret);
+    }
+
+    //Frequency avoid adjust if need
+    if (priv_adv.priv_tbl.fa_dese) {
+        if ((ret = priv_adv.priv_tbl.fa_dese(parm->freq, NULL)) < 0) {
+            goto out;
+        }
+
+        WCN_DBG(FM_INF | MAIN, "FA %d\n", ret);
+    }
+
+    //MCU clock adjust if need
+    if (priv_adv.priv_tbl.mcu_dese) {
+        if ((ret = priv_adv.priv_tbl.mcu_dese(parm->freq, NULL)) < 0) {
+            goto out;
+        }
+
+        WCN_DBG(FM_INF | MAIN, "MCU %d\n", ret);
+    }
+
+    //GPS clock adjust if need
+    if (priv_adv.priv_tbl.gps_dese) {
+        if ((ret = priv_adv.priv_tbl.gps_dese(parm->freq, NULL)) < 0) {
+            goto out;
+        }
+
+        WCN_DBG(FM_INF | MAIN, "GPS %d\n", ret);
+    }
+#endif
+    fm_op_state_set(fm, FM_STA_TUNE);
+    WCN_DBG(FM_ALT | MAIN, "tuning to %d\n", parm->freq);
+
+    if (fm_false == fm_low_ops.bi.setfreq(parm->freq)) {
+        parm->err = FM_TUNE_FAILED;
+        WCN_DBG(FM_ALT | MAIN, "FM tune failed\n");
+        ret = -EPERM;
+    }
+
+//    fm_low_ops.bi.mute(fm_false);
+    fm_op_state_set(fm, FM_STA_PLAY);
+out:
+    FM_UNLOCK(fm_ops_lock);
+    return ret;
+}
+//cqi log tool entry
+fm_s32 fm_cqi_log(void)
+{
+    fm_s32 ret = 0;
+    fm_u16 freq;
+       FMR_ASSERT(fm_low_ops.bi.cqi_log);
+    freq = fm_cur_freq_get();
+    if (0 == fm_get_channel_space(freq)) {
+        freq *= 10;
+    }
+    if((freq != 10000) && (0xffffffff != g_dbg_level))
+    {
+       return -FM_EPARA;
+    }
+       if (FM_LOCK(fm_ops_lock)) 
+               return (-FM_ELOCK);
+       ret = fm_low_ops.bi.cqi_log(8750,10800,2,5);
+    FM_UNLOCK(fm_ops_lock);
+       return ret;
+}
+/*fm soft mute tune function*/
+fm_s32 fm_soft_mute_tune(struct fm *fm, struct fm_softmute_tune_t *parm)
+{
+    fm_s32 ret = 0;
+
+       FMR_ASSERT(fm_low_ops.bi.softmute_tune);
+       
+       if (FM_LOCK(fm_ops_lock)) 
+               return (-FM_ELOCK);
+       
+       
+       if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) 
+       {
+               parm->valid = fm_false;
+               ret = -EPERM;
+               goto out;
+       }
+       
+       //        fm_low_ops.bi.mute(fm_true);
+       WCN_DBG(FM_NTC | MAIN, "+%s():[freq=%d]\n", __func__, parm->freq);
+       //fm_op_state_set(fm, FM_STA_TUNE);
+       
+       if (fm_false == fm_low_ops.bi.softmute_tune(parm->freq,&parm->rssi,&parm->valid)) 
+       {
+               parm->valid = fm_false;
+               WCN_DBG(FM_ALT | MAIN, "sm tune failed\n");
+               ret = -EPERM;
+       }
+       
+//       fm_low_ops.bi.mute(fm_false);
+out:
+       WCN_DBG(FM_NTC | MAIN, "-%s()\n", __func__);
+       FM_UNLOCK(fm_ops_lock);
+               
+       return ret;
+}
+fm_s32 fm_over_bt(struct fm *fm, fm_s32 flag)
+{
+    fm_s32 ret = 0;
+       FMR_ASSERT(fm_low_ops.bi.fm_via_bt);
+       
+    if (fm_pwr_state_get(fm) != FM_PWR_RX_ON) 
+    {
+        return -EPERM;
+    }
+       if (FM_LOCK(fm_ops_lock)) 
+               return (-FM_ELOCK);
+   
+    ret = fm_low_ops.bi.fm_via_bt(flag);
+    if(ret)
+    {
+        WCN_DBG(FM_ALT | MAIN,"%s(),failed!\n", __func__);
+    }
+    else
+    {
+       fm->via_bt = flag;
+    }
+    WCN_DBG(FM_NTC | MAIN,"%s(),[ret=%d]!\n", __func__, ret);
+       FM_UNLOCK(fm_ops_lock);
+    return ret;
+}
+fm_s32 fm_tx_support(struct fm *fm, fm_s32 *support)
+{
+       if (FM_LOCK(fm_ops_lock)) 
+               return (-FM_ELOCK);
+       if(fm_low_ops.bi.tx_support)
+       {
+               fm_low_ops.bi.tx_support(support);
+       }
+       else
+       {
+               *support=0;
+       }
+    WCN_DBG(FM_NTC | MAIN,"%s(),[%d]!\n", __func__, *support);
+       FM_UNLOCK(fm_ops_lock);
+       return 0;
+}
+fm_s32 fm_rdstx_support(struct fm *fm, fm_s32 *support)
+{
+       if (FM_LOCK(fm_ops_lock)) 
+               return (-FM_ELOCK);
+       if(fm_low_ops.ri.rdstx_support)
+       {
+               fm_low_ops.ri.rdstx_support(support);
+       }
+       else
+       {
+               *support=0;
+       }
+    WCN_DBG(FM_NTC | MAIN,"support=[%d]!\n", *support);
+       FM_UNLOCK(fm_ops_lock);
+       return 0;
+}
+fm_s32 fm_rdstx_enable(struct fm *fm, fm_s32 *support)
+{
+       if (FM_LOCK(fm_ops_lock)) 
+               return (-FM_ELOCK);
+       if(fm->rdstx_on)
+       {
+               *support=1;
+       }
+       else
+       {
+               *support=0;
+       }
+    WCN_DBG(FM_NTC | MAIN,"rds tx enable=[%d]!\n", *support);
+       FM_UNLOCK(fm_ops_lock);
+       return 0;
+}
+
+static void fm_timer_func(unsigned long data)
+{
+    struct fm *fm = g_fm_struct;
+
+    if (FM_LOCK(fm_timer_lock)) return;
+
+    if (fm_timer_sys->update(fm_timer_sys)) {
+               WCN_DBG(FM_NTC | MAIN, "timer skip\n");
+        goto out; //fm timer is stoped before timeout
+    }
+
+    if (fm != NULL) {
+               WCN_DBG(FM_NTC | MAIN, "timer:rds_wk\n");
+        fm->timer_wkthd->add_work(fm->timer_wkthd, fm->rds_wk);
+    }
+
+out:
+    FM_UNLOCK(fm_timer_lock);
+}
+
+
+static void fmtx_timer_func(unsigned long data)
+{
+    struct fm *fm = g_fm_struct;
+    fm_s32 vco_cycle = 1;
+
+    if (FM_LOCK(fm_timer_lock)) return;
+
+    fm_timer_sys->count++; 
+    if (fm != NULL) 
+    {
+               //schedule tx pwr ctrl work if need
+               if(fm->txpwrctl < 1)
+               {
+                       WCN_DBG(FM_WAR | MAIN,"tx power ctl time err\n");
+                       fm->txpwrctl = FM_TX_PWR_CTRL_INVAL_MIN;
+               }
+               if((fm_timer_sys->tx_pwr_ctrl_en == FM_TX_PWR_CTRL_ENABLE) && (fm_timer_sys->count%fm->txpwrctl == 0))
+               {
+                       WCN_DBG(FM_NTC | MAIN, "Tx timer:fm_tx_power_ctrl_work\n");
+                       fm->timer_wkthd->add_work(fm->timer_wkthd, fm->fm_tx_power_ctrl_work); 
+               }
+               /*
+               //schedule tx RTC ctrl work if need
+               if((timer->tx_rtc_ctrl_en == FM_TX_RTC_CTRL_ENABLE)&& (timer->count%FM_TX_RTC_CTRL_INTERVAL == 0)){
+                       FM_LOG_DBG(D_TIMER,"fm_tx_rtc_ctrl_work, ticks:%d\n", jiffies_to_msecs(jiffies));
+                       queue_work(fm->fm_timer_workqueue, &fm->fm_tx_rtc_ctrl_work); 
+               }*/
+               //schedule tx desense with wifi/bt work if need
+               if(fm->vcooff < 1)
+               {
+                       WCN_DBG(FM_WAR | MAIN,"tx vco tracking time err\n");
+                       fm->vcooff = FM_TX_VCO_OFF_MIN;
+               }
+               vco_cycle = fm->vcooff + fm->vcoon/1000;
+               if((fm_timer_sys->tx_desense_en == FM_TX_DESENSE_ENABLE) && (fm_timer_sys->count%vco_cycle == 0))
+               {
+                       WCN_DBG(FM_NTC | MAIN, "Tx timer:fm_tx_desense_wifi_work\n");
+                       fm->timer_wkthd->add_work(fm->timer_wkthd, fm->fm_tx_desense_wifi_work); 
+               }
+    }
+    if (fm_timer_sys->update(fm_timer_sys)) {
+               WCN_DBG(FM_NTC | MAIN, "timer skip\n");
+        goto out; //fm timer is stoped before timeout
+    }
+
+out:
+    FM_UNLOCK(fm_timer_lock);
+}
+
+static void fm_tx_power_ctrl_worker_func(unsigned long data)
+{
+    fm_s32 ctrl = 0,ret=0;
+    struct fm *fm = g_fm_struct;
+
+    WCN_DBG(FM_NTC | MAIN,"+%s():\n", __func__);
+    
+       if(fm_low_ops.bi.tx_pwr_ctrl == NULL)
+               return;
+    if (FM_LOCK(fm_rxtx_lock)) return;
+    
+    if(fm_pwr_state_get(fm) != FM_PWR_TX_ON){
+        WCN_DBG(FM_ERR | MAIN,"FM is not on TX mode\n");
+        goto out;
+    }
+    
+    ctrl = fm->tx_pwr;
+    WCN_DBG(FM_NTC | MAIN,"tx pwr %ddb\n", ctrl);
+    ret = fm_low_ops.bi.tx_pwr_ctrl(fm_cur_freq_get(), &ctrl);
+    if(ret)
+    {
+        WCN_DBG(FM_ERR | MAIN,"tx_pwr_ctrl fail\n");
+    }
+    
+out:
+    FM_UNLOCK(fm_rxtx_lock);
+    WCN_DBG(FM_NTC | MAIN,"-%s()\n", __func__);
+    return;
+}
+static void fm_tx_rtc_ctrl_worker_func(unsigned long data)
+{
+    fm_s32 ret = 0;
+    fm_s32 ctrl = 0;
+    struct fm_gps_rtc_info rtcInfo;
+    //struct timeval curTime;
+    //struct fm *fm = (struct fm*)fm_cb;
+    unsigned long curTime = 0;
+
+    WCN_DBG(FM_NTC | MAIN,"+%s():\n", __func__);
+
+    if(FM_LOCK(fm_rtc_mutex)) return;
+    
+    if(gps_rtc_info.flag == FM_GPS_RTC_INFO_NEW){
+        memcpy(&rtcInfo, &gps_rtc_info, sizeof(struct fm_gps_rtc_info));
+        gps_rtc_info.flag = FM_GPS_RTC_INFO_OLD;
+        FM_UNLOCK(fm_rtc_mutex);
+    }else{
+        WCN_DBG(FM_NTC | MAIN,"there's no new rtc drift info\n");
+        FM_UNLOCK(fm_rtc_mutex);
+        goto out;
+    }
+
+    if(rtcInfo.age > rtcInfo.ageThd){
+       WCN_DBG(FM_WAR | MAIN,"age over it's threshlod\n");
+       goto out;
+    }
+    if((rtcInfo.drift <= rtcInfo.driftThd) && (rtcInfo.drift >= -rtcInfo.driftThd)){
+       WCN_DBG(FM_WAR | MAIN,"drift over it's MIN threshlod\n");
+       goto out;
+    }
+
+    if(rtcInfo.drift > FM_GPS_RTC_DRIFT_MAX){
+        WCN_DBG(FM_WAR | MAIN,"drift over it's +MAX threshlod\n");
+        rtcInfo.drift = FM_GPS_RTC_DRIFT_MAX;
+        goto out;
+    }else if(rtcInfo.drift < -FM_GPS_RTC_DRIFT_MAX){
+        WCN_DBG(FM_WAR | MAIN,"drift over it's -MAX threshlod\n");
+        rtcInfo.drift = -FM_GPS_RTC_DRIFT_MAX;
+        goto out;
+    }
+    /*
+    //get current time
+    do_gettimeofday(&curTime);
+    if((curTime.tv_sec - rtcInfo.tv.tv_sec) > rtcInfo.tvThd.tv_sec){
+        FM_LOG_WAR(D_MAIN,"time diff over it's threshlod\n");
+        goto out;
+    }*/
+    curTime = jiffies;
+    if(((long)curTime - (long)rtcInfo.stamp)/HZ > rtcInfo.tvThd.tv_sec){
+        WCN_DBG(FM_WAR | MAIN,"time diff over it's threshlod\n");
+        goto out;
+    }
+    if(fm_low_ops.bi.rtc_drift_ctrl != NULL)
+    {
+        ctrl = rtcInfo.drift;
+               WCN_DBG(FM_NTC | MAIN,"RTC_drift_ctrl[0x%08x]\n", ctrl);
+        if((ret = fm_low_ops.bi.rtc_drift_ctrl(fm_cur_freq_get(), &ctrl)))
+            goto out;
+    }
+out:
+    WCN_DBG(FM_NTC | MAIN,"-%s()\n", __func__);
+    return;
+} 
+
+static void fm_tx_desense_wifi_worker_func(unsigned long data)
+{
+    fm_s32 ret = 0;
+    fm_s32 ctrl = 0;
+    struct fm *fm = g_fm_struct;
+
+    WCN_DBG(FM_NTC | MAIN,"+%s():\n", __func__);
+
+    if (FM_LOCK(fm_rxtx_lock)) return;
+    
+    if(fm_pwr_state_get(fm) != FM_PWR_TX_ON){
+        WCN_DBG(FM_ERR | MAIN,"FM is not on TX mode\n");
+        goto out;
+    }
+    
+    fm_tx_rtc_ctrl_worker_func(0);
+
+    ctrl = fm->vcoon;
+    if(fm_low_ops.bi.tx_desense_wifi)
+    {
+           WCN_DBG(FM_NTC | MAIN,"tx_desense_wifi[%d]\n", ctrl);
+               ret = fm_low_ops.bi.tx_desense_wifi(fm_cur_freq_get(), &ctrl);
+           if(ret)
+           {
+               WCN_DBG(FM_ERR | MAIN,"tx_desense_wifi fail\n");
+           }
+       }
+out:
+    FM_UNLOCK(fm_rxtx_lock);
+    WCN_DBG(FM_NTC | MAIN,"-%s()\n", __func__);
+    return;
+} 
+
+/*
+************************************************************************************
+Function:         fm_get_gps_rtc_info()
+
+Description:     get GPS RTC drift info, and this function should not block
+
+Date:              2011/04/10
+
+Return Value:   success:0, failed: error coe
+************************************************************************************
+*/
+fm_s32 fm_get_gps_rtc_info(struct fm_gps_rtc_info *src)
+{
+    fm_s32 ret = 0;
+//    fm_s32 retry_cnt = 0;
+       struct fm_gps_rtc_info *dst=&gps_rtc_info; 
+    
+    FMR_ASSERT(src);
+    FMR_ASSERT(dst);
+
+    if(src->retryCnt > 0){
+        dst->retryCnt = src->retryCnt;
+        WCN_DBG(FM_NTC | MAIN,"%s, new [retryCnt=%d]\n", __func__, dst->retryCnt);
+    }
+    if(src->ageThd > 0){
+        dst->ageThd = src->ageThd;
+        WCN_DBG(FM_NTC | MAIN,"%s, new [ageThd=%d]\n", __func__, dst->ageThd);
+    }
+    if(src->driftThd > 0){
+        dst->driftThd = src->driftThd;
+        WCN_DBG(FM_NTC | MAIN,"%s, new [driftThd=%d]\n", __func__, dst->driftThd);
+    }
+    if(src->tvThd.tv_sec > 0){
+        dst->tvThd.tv_sec = src->tvThd.tv_sec;
+        WCN_DBG(FM_NTC | MAIN,"%s, new [tvThd=%d]\n", __func__, (fm_s32)dst->tvThd.tv_sec);
+    }
+    ret = fm_rtc_mutex->trylock(fm_rtc_mutex,dst->retryCnt);
+    if(ret)
+    {
+               goto out;
+    }
+    dst->age = src->age;
+    dst->drift = src->drift;
+    dst->stamp = jiffies; //get curren time stamp
+    dst->flag = FM_GPS_RTC_INFO_NEW;
+    
+    FM_UNLOCK(fm_rtc_mutex);
+
+   /*
+    //send event to info fm_tx_rtc_ctrl_work
+    if(timer_sys.tx_rtc_ctrl_en == FM_TX_RTC_CTRL_ENABLE){
+        FM_LOG_DBG(D_TIMER,"fm_tx_rtc_ctrl_work, ticks:%d\n", jiffies_to_msecs(jiffies));
+        queue_work(fm->fm_timer_workqueue, &fm->fm_tx_rtc_ctrl_work); 
+    }
+    */
+    
+out:
+    return ret;
+}
+
+static void fm_enable_rds_BlerCheck(struct fm *fm)
+{
+    if (FM_LOCK(fm_timer_lock)) return;
+    fm_timer_sys->start(fm_timer_sys);
+    FM_UNLOCK(fm_timer_lock);
+}
+
+static void fm_disable_rds_BlerCheck(void)
+{
+    if (FM_LOCK(fm_timer_lock)) return;
+    fm_timer_sys->stop(fm_timer_sys);
+    FM_UNLOCK(fm_timer_lock);
+}
+
+void fm_rds_reset_work_func(unsigned long data)
+{
+    fm_s32 ret = 0;
+
+    if (!fm_low_ops.ri.rds_blercheck) {
+        return;
+    }
+    if (FM_LOCK(fm_rxtx_lock)) return;
+
+    if (FM_LOCK(fm_rds_cnt)) return;
+    ret = fm_low_ops.ri.rds_blercheck(g_fm_struct->pstRDSData);
+
+       WCN_DBG(FM_NTC | MAIN, "Addr_Cnt=%x\n",g_fm_struct->pstRDSData->AF_Data.Addr_Cnt);
+       if(g_fm_struct->pstRDSData->AF_Data.Addr_Cnt == 0xFF)//check af list get,can't use event==af_list because event will clear after read rds every time
+       {
+               g_fm_struct->pstRDSData->event_status |= RDS_EVENT_AF;
+       }
+    if (!ret && g_fm_struct->pstRDSData->event_status) 
+    {
+        FM_EVENT_SEND(g_fm_struct->rds_event, FM_RDS_DATA_READY);
+    }
+       WCN_DBG(FM_NTC | MAIN, "rds event check=%x\n",g_fm_struct->pstRDSData->event_status);
+    FM_UNLOCK(fm_rds_cnt);
+    FM_UNLOCK(fm_rxtx_lock);
+}
+
+
+void fm_subsys_reset_work_func(unsigned long data)
+{
+    g_dbg_level = 0xffffffff;
+    if (FM_LOCK(fm_ops_lock)) return;
+
+    fm_sys_state_set(g_fm_struct, FM_SUBSYS_RST_START);
+    
+    if (g_fm_struct->chipon == fm_false)
+       {
+        WCN_DBG(FM_ALT | MAIN, "no need do recover\n");
+        goto out;
+    }
+    // subsystem power off
+    fm_low_ops.bi.pwroff(0);
+    
+    // prepare to reset
+    
+    // wait 3s
+    fm_low_ops.bi.msdelay(2000);
+    
+    // subsystem power on
+    fm_low_ops.bi.pwron(0);
+    
+    // recover context
+    if (g_fm_struct->chipon == fm_false) {
+        fm_low_ops.bi.pwroff(0);
+        WCN_DBG(FM_ALT | MAIN, "no need do recover\n");
+        goto out;
+    }
+
+    if (FM_PWR_RX_ON == fm_pwr_state_get(g_fm_struct)) {
+        fm_low_ops.bi.pwrupseq(&g_fm_struct->chip_id, &g_fm_struct->device_id);
+    } else {
+        WCN_DBG(FM_ALT | MAIN, "no need do re-powerup\n");
+        goto out;
+    }
+
+    fm_low_ops.bi.anaswitch(g_fm_struct->ana_type);
+    
+    fm_low_ops.bi.setfreq(fm_cur_freq_get()); 
+
+    fm_low_ops.bi.volset((fm_u8)g_fm_struct->vol);
+
+    fm_low_ops.bi.mute(g_fm_struct->mute);
+
+    fm_low_ops.ri.rds_onoff(g_fm_struct->pstRDSData, g_fm_struct->rds_on);
+
+    WCN_DBG(FM_ALT | MAIN, "recover done\n");
+
+out:
+    fm_sys_state_set(g_fm_struct, FM_SUBSYS_RST_END);
+    fm_sys_state_set(g_fm_struct, FM_SUBSYS_RST_OFF);
+
+    FM_UNLOCK(fm_ops_lock);
+    g_dbg_level = 0xfffffff5;
+}
+
+static void fm_eint_handler(void)
+{
+    struct fm *fm = g_fm_struct;
+    WCN_DBG(FM_DBG | MAIN, "intr occur, ticks:%d\n", jiffies_to_msecs(jiffies));
+
+    if (fm != NULL) {
+        fm->eint_wkthd->add_work(fm->eint_wkthd, fm->eint_wk);
+    }
+}
+
+static fm_s32 fm_rds_parser(struct rds_rx_t *rds_raw, fm_s32 rds_size)
+{
+    struct fm *fm = g_fm_struct;//(struct fm *)work->data;
+    rds_t *pstRDSData = fm->pstRDSData;
+
+    if (FM_LOCK(fm_read_lock)) return (-FM_ELOCK);
+    //parsing RDS data
+    fm_low_ops.ri.rds_parser(pstRDSData, rds_raw, rds_size, fm_cur_freq_get);
+    FM_UNLOCK(fm_read_lock);
+
+    if ((pstRDSData->event_status != 0x0000) && (pstRDSData->event_status != RDS_EVENT_AF_LIST)) {
+        WCN_DBG(FM_NTC | MAIN, "Notify user to read, [event:%04x]\n", pstRDSData->event_status);
+        FM_EVENT_SEND(fm->rds_event, FM_RDS_DATA_READY);
+    }
+
+    return 0;
+}
+
+static void fm_eint_work_func(unsigned long data)
+{
+    fm_event_parser(fm_rds_parser);
+    //re-enable eint if need
+    fm_enable_eint();
+}
+
+static fm_s32 fm_callback_register(struct fm_lowlevel_ops *ops)
+{
+    FMR_ASSERT(ops);
+
+    ops->cb.cur_freq_get = fm_cur_freq_get;
+    ops->cb.cur_freq_set = fm_cur_freq_set;
+    return 0;
+}
+
+static fm_s32 fm_callback_unregister(struct fm_lowlevel_ops *ops)
+{
+    FMR_ASSERT(ops);
+
+    fm_memset(&ops->cb, 0, sizeof(struct fm_callback));
+    return 0;
+}
+
+
+static fm_s32 fm_para_init(struct fm *fmp)
+{
+    FMR_ASSERT(fmp);
+
+    fmp->band = FM_BAND_SPECIAL;
+    fmp->min_freq = FM_RX_BAND_FREQ_L;
+    fmp->max_freq = FM_RX_BAND_FREQ_H;
+    fmp->cur_freq = 0;
+    
+    return 0;
+}
+
+fm_s32 fm_cust_config_setup(fm_s8 * filename)
+{
+       fm_s32 ret;
+#if (defined(MT6620_FM)||defined(MT6628_FM))
+#ifdef MT6628_FM       
+       ret = MT6628fm_cust_config_setup(filename);
+       if(ret < 0)
+       {
+        WCN_DBG(FM_ERR | MAIN, "MT6628fm_cust_config_setup failed\n");
+       }
+#endif
+#ifdef MT6620_FM
+       ret = MT6620fm_cust_config_setup(filename);
+       if(ret < 0)
+       {
+        WCN_DBG(FM_ERR | MAIN, "MT6620fm_cust_config_setup failed\n");
+       }
+#endif
+#else
+       fm_cust_config(filename);
+       if(ret < 0)
+       {
+        WCN_DBG(FM_ERR | MAIN, "fm_cust_config failed\n");
+       }
+#endif
+       return ret;
+}
+
+struct fm* fm_dev_init(fm_u32 arg) 
+{
+    fm_s32 ret = 0;
+    struct fm *fm = NULL;
+
+//    if (!fm_low_ops.ri.rds_bci_get)
+//        return NULL;
+
+//    if (!fm_low_ops.bi.chipid_get)
+//        return NULL;
+
+    //alloc fm main data structure
+    if (!(fm = fm_zalloc(sizeof(struct fm)))) {
+        WCN_DBG(FM_ALT | MAIN, "-ENOMEM\n");
+        ret = -ENOMEM;
+        goto ERR_EXIT;
+    }
+
+    fm->ref = 0;
+    fm->chipon = fm_false;
+    fm_pwr_state_set(fm, FM_PWR_OFF);
+//    fm->chip_id = fm_low_ops.bi.chipid_get();
+       //FM Tx
+       fm->vcoon = FM_TX_VCO_ON_DEFAULT;
+       fm->vcooff = FM_TX_VCO_OFF_DEFAULT;
+       fm->txpwrctl = FM_TX_PWR_CTRL_INVAL_DEFAULT;
+    fm->tx_pwr = FM_TX_PWR_LEVEL_MAX;
+    gps_rtc_info.err = 0;
+    gps_rtc_info.age = 0;
+    gps_rtc_info.drift = 0;
+    gps_rtc_info.tv.tv_sec = 0;
+    gps_rtc_info.tv.tv_usec = 0;
+    gps_rtc_info.ageThd = FM_GPS_RTC_AGE_TH;
+    gps_rtc_info.driftThd = FM_GPS_RTC_DRIFT_TH;
+    gps_rtc_info.tvThd.tv_sec = FM_GPS_RTC_TIME_DIFF_TH;
+    gps_rtc_info.retryCnt = FM_GPS_RTC_RETRY_CNT;
+    gps_rtc_info.flag = FM_GPS_RTC_INFO_OLD;
+       
+    if (!(fm->rds_event = fm_flag_event_create("fm_rds_event"))) {
+        WCN_DBG(FM_ALT | MAIN, "-ENOMEM for RDS event\n");
+        ret = -ENOMEM;
+        goto ERR_EXIT;
+    }
+
+    fm_flag_event_get(fm->rds_event);
+
+    //alloc fm rds data structure
+    if (!(fm->pstRDSData = fm_zalloc(sizeof(rds_t)))) {
+        WCN_DBG(FM_ALT | MAIN, "-ENOMEM for RDS\n");
+        ret = -ENOMEM;
+        goto ERR_EXIT;
+    }
+
+    g_fm_struct = fm;
+
+    fm->timer_wkthd = fm_workthread_create("fm_timer_wq");
+
+    if (!fm->timer_wkthd) {
+        WCN_DBG(FM_ALT | MAIN, "-ENOMEM for fm_timer_wq\n");
+        ret = -ENOMEM;
+        goto ERR_EXIT;
+    }
+
+    fm_workthread_get(fm->timer_wkthd);
+
+    fm->eint_wkthd = fm_workthread_create("fm_eint_wq");
+
+    if (!fm->eint_wkthd) {
+        WCN_DBG(FM_ALT | MAIN, "-ENOMEM for fm_eint_wq\n");
+        ret = -ENOMEM;
+        goto ERR_EXIT;
+    }
+
+    fm_workthread_get(fm->eint_wkthd);
+
+    fm->eint_wk = fm_work_create("fm_eint_work");
+
+    if (!fm->eint_wk) {
+        WCN_DBG(FM_ALT | MAIN, "-ENOMEM for eint_wk\n");
+        ret = -ENOMEM;
+        goto ERR_EXIT;
+    } else {
+        fm_work_get(fm->eint_wk);
+        fm->eint_wk->init(fm->eint_wk, fm_eint_work_func, (unsigned long)fm);
+    }
+
+    // create reset work
+    fm->rst_wk = fm_work_create("fm_rst_work");
+
+    if (!fm->rst_wk) {
+        WCN_DBG(FM_ALT | MAIN, "-ENOMEM for rst_wk\n");
+        ret = -ENOMEM;
+        goto ERR_EXIT;
+    } else {
+        fm_work_get(fm->rst_wk);
+        fm->rst_wk->init(fm->rst_wk, fm_subsys_reset_work_func, (unsigned long)fm);
+    }
+
+    fm->rds_wk = fm_work_create("fm_rds_work");
+    if (!fm->rds_wk) {
+        WCN_DBG(FM_ALT | MAIN, "-ENOMEM for rds_wk\n");
+        ret = -ENOMEM;
+        goto ERR_EXIT;
+    } else {
+        fm_work_get(fm->rds_wk);
+        fm->rds_wk->init(fm->rds_wk, fm_rds_reset_work_func, (unsigned long)fm);
+    }
+    
+    fm->fm_tx_power_ctrl_work = fm_work_create("tx_pwr_ctl_work");
+    if (!fm->fm_tx_power_ctrl_work) {
+        WCN_DBG(FM_ALT | MAIN, "-ENOMEM for tx_pwr_ctl_work\n");
+        ret = -ENOMEM;
+        goto ERR_EXIT;
+    } else {
+        fm_work_get(fm->fm_tx_power_ctrl_work);
+        fm->fm_tx_power_ctrl_work->init(fm->fm_tx_power_ctrl_work, fm_tx_power_ctrl_worker_func, (unsigned long)fm);
+    }
+    
+    fm->fm_tx_desense_wifi_work = fm_work_create("tx_desen_wifi_work");
+    if (!fm->fm_tx_desense_wifi_work) {
+        WCN_DBG(FM_ALT | MAIN, "-ENOMEM for tx_desen_wifi_work\n");
+        ret = -ENOMEM;
+        goto ERR_EXIT;
+    } else {
+        fm_work_get(fm->fm_tx_desense_wifi_work);
+        fm->fm_tx_desense_wifi_work->init(fm->fm_tx_desense_wifi_work, fm_tx_desense_wifi_worker_func, (unsigned long)fm);
+    }
+
+    //fm timer was created in fm_env_setp()
+//    fm_timer_sys->init(fm_timer_sys, fm_timer_func, (unsigned long)g_fm_struct, fm_low_ops.ri.rds_bci_get(), 0);
+//    fm_timer_sys->start(fm_timer_sys);
+
+    //init customer config parameter
+    fm_cust_config_setup(NULL);
+
+    fm_para_init(fm);
+    
+    return g_fm_struct;
+
+ERR_EXIT:
+
+    if (fm->eint_wkthd) {
+        ret = fm_workthread_put(fm->eint_wkthd);
+
+        if (!ret)
+            fm->eint_wkthd = NULL;
+    }
+
+    if (fm->timer_wkthd) {
+        ret = fm_workthread_put(fm->timer_wkthd);
+
+        if (!ret)
+            fm->timer_wkthd = NULL;
+    }
+
+    if (fm->eint_wk) {
+        ret = fm_work_put(fm->eint_wk);
+
+        if (!ret)
+            fm->eint_wk = NULL;
+    }
+
+    if (fm->rds_wk) {
+        ret = fm_work_put(fm->rds_wk);
+
+        if (!ret)
+            fm->rds_wk = NULL;
+    }
+
+    if (fm->rst_wk) {
+        ret = fm_work_put(fm->rst_wk);
+
+        if (!ret)
+            fm->rst_wk = NULL;
+    }
+    
+    if (fm->fm_tx_desense_wifi_work) {
+        ret = fm_work_put(fm->fm_tx_desense_wifi_work);
+
+        if (!ret)
+            fm->fm_tx_desense_wifi_work = NULL;
+    }
+    
+    if (fm->fm_tx_power_ctrl_work) {
+        ret = fm_work_put(fm->fm_tx_power_ctrl_work);
+
+        if (!ret)
+            fm->fm_tx_power_ctrl_work = NULL;
+    }
+    
+    if (fm->pstRDSData) {
+        fm_free(fm->pstRDSData);
+        fm->pstRDSData = NULL;
+    }
+
+    fm_free(fm);
+    g_fm_struct = NULL;
+    return NULL;
+}
+
+fm_s32 fm_dev_destroy(struct fm *fm)
+{
+    fm_s32 ret = 0;
+
+    WCN_DBG(FM_DBG | MAIN, "%s\n", __func__);
+
+    fm_timer_sys->stop(fm_timer_sys);
+
+    if (fm->eint_wkthd) {
+        ret = fm_workthread_put(fm->eint_wkthd);
+
+        if (!ret)
+            fm->eint_wkthd = NULL;
+    }
+
+    if (fm->timer_wkthd) {
+        ret = fm_workthread_put(fm->timer_wkthd);
+
+        if (!ret)
+            fm->timer_wkthd = NULL;
+    }
+
+    if (fm->eint_wk) {
+        ret = fm_work_put(fm->eint_wk);
+
+        if (!ret)
+            fm->eint_wk = NULL;
+    }
+
+    if (fm->rds_wk) {
+        ret = fm_work_put(fm->rds_wk);
+
+        if (!ret)
+            fm->rds_wk = NULL;
+    }
+
+    if (fm->rst_wk) {
+        ret = fm_work_put(fm->rst_wk);
+
+        if (!ret)
+            fm->rst_wk = NULL;
+    }
+    
+    if (fm->pstRDSData) {
+        fm_free(fm->pstRDSData);
+        fm->pstRDSData = NULL;
+    }
+
+    if (fm->pstRDSData) {
+        fm_free(fm->pstRDSData);
+        fm->pstRDSData = NULL;
+    }
+
+    fm_flag_event_put(fm->rds_event);
+
+    // free all memory
+    if (fm) {
+        fm_free(fm);
+        fm = NULL;
+        g_fm_struct = NULL;
+    }
+
+    return ret;
+}
+
+fm_s32 fm_env_setup(void)
+{
+    fm_s32 ret = 0;
+
+    WCN_DBG(FM_NTC | MAIN, "%s\n", __func__);
+#if (defined(MT6620_FM)||defined(MT6628_FM))
+#ifdef MT6620_FM       
+    //register call back functions
+    ret = fm_callback_register(&MT6620fm_low_ops);
+    if (ret) {
+        return ret;
+    }
+    WCN_DBG(FM_NTC | MAIN, "1. fm callback registered\n");
+    //get low level functions
+    ret = MT6620fm_low_ops_register(&MT6620fm_low_ops);
+    if (ret) {
+        return ret;
+    }
+    WCN_DBG(FM_NTC | MAIN, "2. fm low ops registered\n");
+    //get rds level functions
+    ret = MT6620fm_rds_ops_register(&MT6620fm_low_ops);
+    if (ret) {
+        return ret;
+    }
+    WCN_DBG(FM_NTC | MAIN, "3. fm rds ops registered\n");
+#endif 
+#ifdef MT6628_FM       
+    //register call back functions
+    ret = fm_callback_register(&MT6628fm_low_ops);
+    if (ret) {
+        return ret;
+    }
+    WCN_DBG(FM_NTC | MAIN, "1. fm callback registered\n");
+    //get low level functions
+    ret = MT6628fm_low_ops_register(&MT6628fm_low_ops);
+    if (ret) {
+        return ret;
+    }
+    WCN_DBG(FM_NTC | MAIN, "2. fm low ops registered\n");
+    //get rds level functions
+    ret = MT6628fm_rds_ops_register(&MT6628fm_low_ops);
+    if (ret) {
+        return ret;
+    }
+    WCN_DBG(FM_NTC | MAIN, "3. fm rds ops registered\n");
+#endif 
+#else 
+    //register call back functions
+    ret = fm_callback_register(&fm_low_ops);
+    if (ret) {
+        return ret;
+    }
+    WCN_DBG(FM_NTC | MAIN, "1. fm callback registered\n");
+    //get low level functions
+    ret = fm_low_ops_register(&fm_low_ops);
+
+    if (ret) {
+        return ret;
+    }
+
+    WCN_DBG(FM_NTC | MAIN, "2. fm low ops registered\n");
+    //get rds level functions
+    ret = fm_rds_ops_register(&fm_low_ops);
+
+    if (ret) {
+        return ret;
+    }
+    WCN_DBG(FM_NTC | MAIN, "3. fm rds ops registered\n");
+#endif
+
+    fm_ops_lock = fm_lock_create("ops_lock");
+
+    if (!fm_ops_lock) {
+        return -1;
+    }
+
+    fm_read_lock = fm_lock_create("rds_read");
+
+    if (!fm_read_lock) {
+        return -1;
+    }
+    
+    fm_rds_cnt = fm_lock_create("rds_cnt");
+
+    if (!fm_rds_cnt) {
+        return -1;
+    }
+
+    fm_timer_lock = fm_spin_lock_create("timer_lock");
+
+    if (!fm_timer_lock) {
+        return -1;
+    }
+       fm_rxtx_lock = fm_lock_create("rxtx_lock");
+    if (!fm_rxtx_lock) {
+        return -1;
+    }
+       fm_rtc_mutex = fm_lock_create("rxtx_lock");
+    if (!fm_rxtx_lock) {
+        return -1;
+    }
+
+    fm_lock_get(fm_ops_lock);
+    fm_lock_get(fm_read_lock);
+    fm_lock_get(fm_rds_cnt);
+    fm_spin_lock_get(fm_timer_lock);
+    fm_lock_get(fm_rxtx_lock);
+    WCN_DBG(FM_NTC | MAIN, "4. fm locks created\n");
+
+    fm_timer_sys = fm_timer_create("fm_sys_timer");
+
+    if (!fm_timer_sys) {
+        return -1;
+    }
+
+    fm_timer_get(fm_timer_sys);
+    WCN_DBG(FM_NTC | MAIN, "5. fm timer created\n");
+
+    ret = fm_link_setup((void*)fm_wholechip_rst_cb);
+
+    if (ret) {
+        WCN_DBG(FM_ERR | MAIN, "fm link setup Failed\n");
+        return -1;
+    }
+
+    return ret;
+}
+
+fm_s32 fm_env_destroy(void)
+{
+    fm_s32 ret = 0;
+
+    WCN_DBG(FM_NTC | MAIN, "%s\n", __func__);
+
+    fm_link_release();
+
+#if (defined(MT6620_FM)||defined(MT6628_FM))
+#if defined(MT6620_FM)
+    //register call back functions
+               ret = fm_callback_unregister(&MT6620fm_low_ops);
+
+    if (ret) {
+        return -1;
+    }
+               //put low level functions
+               ret = MT6620fm_low_ops_unregister(&MT6620fm_low_ops);
+       
+               if (ret) {
+                       return -1;
+               }
+       
+               //put rds func
+               ret = MT6620fm_rds_ops_unregister(&MT6620fm_low_ops);
+       
+               if (ret) {
+                       return -1;
+               }
+#endif
+#if defined(MT6628_FM)
+               //register call back functions
+               ret = fm_callback_unregister(&MT6628fm_low_ops);
+
+               if (ret) {
+                       return -1;
+               }
+               //put low level functions
+               ret = MT6628fm_low_ops_unregister(&MT6628fm_low_ops);
+
+               if (ret) {
+                       return -1;
+               }
+       
+               //put rds func
+               ret = MT6628fm_rds_ops_unregister(&MT6628fm_low_ops);
+       
+               if (ret) {
+                       return -1;
+               }
+#endif
+#else
+    //register call back functions
+    ret = fm_callback_unregister(&fm_low_ops);
+
+    if (ret) {
+        return -1;
+    }
+    //put low level functions
+    ret = fm_low_ops_unregister(&fm_low_ops);
+
+    if (ret) {
+        return -1;
+    }
+
+    //put rds func
+    ret = fm_rds_ops_unregister(&fm_low_ops);
+
+    if (ret) {
+        return -1;
+    }
+#endif
+    ret = fm_lock_put(fm_ops_lock);
+
+    if (!ret)
+        fm_ops_lock = NULL;
+
+    ret = fm_lock_put(fm_read_lock);
+
+    if (!ret)
+        fm_read_lock = NULL;
+
+    ret = fm_lock_put(fm_rds_cnt);
+
+    if (!ret)
+        fm_rds_cnt = NULL;
+    ret = fm_spin_lock_put(fm_timer_lock);
+
+    if (!ret)
+        fm_timer_lock = NULL;
+
+    ret = fm_timer_put(fm_timer_sys);
+
+    if (!ret)
+        fm_timer_sys = NULL;
+
+    return ret;
+}
+
+#if 0//(!defined(MT6620_FM)&&!defined(MT6628_FM))
+fm_s32 fm_priv_register(struct fm_priv *pri, struct fm_pub *pub)
+{
+    fm_s32 ret = 0;
+    //Basic functions.
+
+    WCN_DBG(FM_NTC | MAIN, "%s\n", __func__);
+    FMR_ASSERT(pri);
+    FMR_ASSERT(pub);
+
+    // functions provided by private module
+    priv_adv.priv_tbl.hl_dese = pri->priv_tbl.hl_dese;
+    priv_adv.priv_tbl.fa_dese = pri->priv_tbl.fa_dese;
+    priv_adv.priv_tbl.mcu_dese = pri->priv_tbl.mcu_dese;
+    priv_adv.priv_tbl.gps_dese = pri->priv_tbl.gps_dese;
+    priv_adv.priv_tbl.chan_para_get = pri->priv_tbl.chan_para_get;
+    priv_adv.priv_tbl.is_dese_chan = pri->priv_tbl.is_dese_chan;
+    priv_adv.state = INITED;
+    priv_adv.data = NULL;
+
+    // for special chip(chip with DSP) use
+    fm_low_ops.cb.chan_para_get = priv_adv.priv_tbl.chan_para_get;
+
+    // private module will use these functions
+    pub->pub_tbl.read = fm_low_ops.bi.read;
+    pub->pub_tbl.write = fm_low_ops.bi.write;
+    pub->pub_tbl.setbits = fm_low_ops.bi.setbits;
+    pub->pub_tbl.rampdown = fm_low_ops.bi.rampdown;
+    pub->pub_tbl.msdelay = fm_low_ops.bi.msdelay;
+    pub->pub_tbl.usdelay = fm_low_ops.bi.usdelay;
+    pub->pub_tbl.log = (fm_s32 (*)(const fm_s8 *arg1, ...))printk;
+    pub->state = INITED;
+    pub->data = NULL;
+
+    return ret;
+}
+
+fm_s32 fm_priv_unregister(struct fm_priv *pri, struct fm_pub *pub)
+{
+    WCN_DBG(FM_NTC | MAIN, "%s\n", __func__);
+
+    //FMR_ASSERT(pri);
+    FMR_ASSERT(pub);
+
+    fm_memset(&priv_adv, 0, sizeof(struct fm_priv));
+    fm_low_ops.cb.chan_para_get = NULL;
+    fm_memset(pub, 0, sizeof(struct fm_pub));
+
+    return 0;
+}
+#endif
+
+/*
+ * GetChannelSpace - get the spcace of gived channel
+ * @freq - value in 760~1080 or 7600~10800
+ *
+ * Return 0, if 760~1080; return 1, if 7600 ~ 10800, else err code < 0
+ */
+fm_s32 fm_get_channel_space(fm_s32 freq)
+{
+    if ((freq >= 760) && (freq <= 1080)) {
+        return 0;
+    } else if ((freq >= 7600) && (freq <= 10800)) {
+        return 1;
+    } else {
+        return -1;
+    }
+}
+
diff --git a/drivers/mtk_wcn_combo/drv_fm/core/fm_module.c b/drivers/mtk_wcn_combo/drv_fm/core/fm_module.c
new file mode 100755 (executable)
index 0000000..bea07e5
--- /dev/null
@@ -0,0 +1,1388 @@
+/* fm_module.c
+ *
+ * (C) Copyright 2011
+ * MediaTek <www.MediaTek.com>
+ * Hongcheng <hongcheng.xia@MediaTek.com>
+ *
+ * FM Radio Driver -- main functions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/cdev.h>
+#include <linux/interrupt.h>
+#include <asm/uaccess.h>
+#include <linux/sched.h>
+#include <linux/delay.h> // udelay()
+
+#include "fm_config.h"
+#include "fm_main.h"
+#include "fm_ioctl.h"
+
+#define FM_PROC_FILE           "fm"
+
+fm_u32 g_dbg_level = 0xfffffff5;  // Debug level of FM
+
+//fm main data structure
+static struct fm *g_fm = NULL;
+//proc file entry
+static struct proc_dir_entry *g_fm_proc = NULL;
+
+//char device interface
+static fm_s32  fm_cdev_setup(struct fm *fm);
+static fm_s32  fm_cdev_destroy(struct fm *fm);
+
+static long  fm_ops_ioctl(struct file *filp, fm_u32 cmd, unsigned long arg);
+static loff_t fm_ops_lseek(struct file *filp, loff_t off, fm_s32 whence);
+static ssize_t fm_ops_read(struct file *filp, char *buf, size_t len, loff_t *off);
+static fm_s32  fm_ops_open(struct inode *inode, struct file *filp);
+static fm_s32  fm_ops_release(struct inode *inode, struct file *filp);
+static fm_s32  fm_ops_flush(struct file *filp,fl_owner_t Id);
+static struct file_operations fm_ops = {
+    .owner = THIS_MODULE,
+    .unlocked_ioctl = fm_ops_ioctl,
+    .llseek = fm_ops_lseek,
+    .read = fm_ops_read,
+    .open = fm_ops_open,
+    .release = fm_ops_release,
+    .flush = fm_ops_flush,
+};
+
+static fm_s32 fm_proc_read(char *page, char **start, off_t off, fm_s32 count, fm_s32 *eof, void *data);
+static fm_s32 fm_proc_write(struct file *file, const char *buffer, unsigned long count, void *data);
+
+
+static struct fm_scan_t parm = {
+    .sr_size = 0,
+    .sr.ch_rssi_buf = NULL,
+};
+
+static long fm_ops_ioctl(struct file *filp, fm_u32 cmd, unsigned long arg)
+{
+    fm_s32 ret = 0;
+    struct fm_platform *plat = container_of(filp->f_dentry->d_inode->i_cdev, struct fm_platform, cdev);
+    struct fm *fm = container_of(plat, struct fm, platform);
+
+    WCN_DBG(FM_NTC | MAIN, "%s---pid(%d)---cmd(0x%08x)---arg(0x%08x)\n", current->comm, current->pid, cmd, (fm_u32)arg);
+
+    if (fm_sys_state_get(fm) != FM_SUBSYS_RST_OFF) {
+        WCN_DBG(FM_ALT | MAIN, "FM subsys is resetting, retry later\n");
+        ret = -FM_ESRST;
+        return ret;
+    }
+    
+    switch (cmd) {
+    case FM_IOCTL_POWERUP: {
+        struct fm_tune_parm parm;
+        WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_POWERUP:0\n");
+
+        if (copy_from_user(&parm, (void*)arg, sizeof(struct fm_tune_parm))) {
+            ret = -EFAULT;
+            goto out;
+        }
+
+        ret = fm_powerup(fm, &parm);
+        if (ret < 0) goto out;
+        ret = fm_tune(fm, &parm);
+        if (ret < 0) goto out;
+
+        if (copy_to_user((void*)arg, &parm, sizeof(struct fm_tune_parm))) {
+            ret = -EFAULT;
+            goto out;
+        }
+               WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_POWERUP:1\n");
+
+        break;
+    }
+
+    case FM_IOCTL_POWERDOWN: {
+        WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_POWERDOWN:0\n");
+        ret = fm_powerdown(fm);
+               WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_POWERDOWN:1\n");
+        break;
+    }
+
+    case FM_IOCTL_TUNE: {
+        struct fm_tune_parm parm;
+        WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_TUNE:0\n");
+
+        if (copy_from_user(&parm, (void*)arg, sizeof(struct fm_tune_parm))) {
+            ret = -EFAULT;
+            goto out;
+        }
+
+        ret = fm_tune(fm, &parm);
+        if (ret < 0) {
+            goto out;
+        }
+
+        if (copy_to_user((void*)arg, &parm, sizeof(struct fm_tune_parm))) {
+            ret = -EFAULT;
+            goto out;
+        }
+
+               WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_TUNE:1\n");
+        break;
+    }
+
+       case FM_IOCTL_SOFT_MUTE_TUNE:
+       {
+        struct fm_softmute_tune_t parm;
+        fm_cqi_log();//cqi log tool
+        WCN_DBG(FM_NTC | MAIN,"......FM_IOCTL_SOFT_MUTE_TUNE......\n");
+        if(copy_from_user(&parm, (void*)arg, sizeof(struct fm_softmute_tune_t)))
+        {
+            ret = -EFAULT;
+            goto out;
+        }
+
+        ret = fm_soft_mute_tune(fm, &parm);
+        if (ret < 0) {
+            goto out;
+        }
+
+        if(copy_to_user((void*)arg, &parm, sizeof(struct fm_softmute_tune_t)))
+        {
+            ret = -EFAULT;
+            goto out;
+        }
+        break;
+       }    
+       case FM_IOCTL_SEEK: {
+        struct fm_seek_parm parm;
+        WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_SEEK:0\n");
+
+        if (copy_from_user(&parm, (void*)arg, sizeof(struct fm_seek_parm))) {
+            ret = -EFAULT;
+            goto out;
+        }
+
+        ret = fm_seek(fm, &parm);
+        if (ret < 0) {
+            goto out;
+        }
+
+        if (copy_to_user((void*)arg, &parm, sizeof(struct fm_seek_parm))) {
+            ret = -EFAULT;
+            goto out;
+        }
+               WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_SEEK:1\n");
+        break;
+    }
+
+    case FM_IOCTL_SCAN: {
+        struct fm_scan_parm parm;
+        WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_SCAN start\n");
+
+        if (copy_from_user(&parm, (void*)arg, sizeof(struct fm_scan_parm))) {
+            WCN_DBG(FM_ALT | MAIN, "copy_from_user failed\n");
+            ret = -EFAULT;
+            goto out;
+        }
+
+        ret = fm_scan(fm, &parm);
+        if (ret < 0) goto out;
+
+        if (copy_to_user((void*)arg, &parm, sizeof(struct fm_scan_parm))) {
+            ret = -EFAULT;
+            goto out;
+        }
+
+               WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_SCAN end\n");
+        break;
+    }
+
+    case FM_IOCTL_TUNE_NEW: {
+        struct fm_tune_t tune_tmp;
+    
+        WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_TUNE_NEW\n");
+    
+        if (copy_from_user(&tune_tmp, (void*)arg, sizeof(struct fm_tune_t))) {
+            WCN_DBG(FM_ERR | MAIN, "tune new copy_from_user error\n");
+            ret = -EFAULT;
+            goto out;
+        }
+    
+        ret = fm_tune_new(fm, &tune_tmp);
+        if (ret < 0) {
+            goto out;
+        }
+            
+        if (copy_to_user((void*)arg, &tune_tmp, sizeof(struct fm_tune_t))) {
+            WCN_DBG(FM_ERR | MAIN, "tune new copy_to_user error\n");
+            ret = -EFAULT;
+            goto out;
+        }
+            
+        break;        
+    }
+
+    case FM_IOCTL_SEEK_NEW: {
+        struct fm_seek_t seek_tmp;
+
+        WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_SEEK_NEW\n");
+        
+        if (copy_from_user(&seek_tmp, (void*)arg, sizeof(struct fm_seek_t))) {
+            WCN_DBG(FM_ERR | MAIN, "seek new copy_from_user error\n");
+            ret = -EFAULT;
+            goto out;
+        }
+        
+        ret = fm_seek_new(fm, &seek_tmp);
+        if (ret < 0) {
+            goto out;
+        }
+
+        if (copy_to_user((void*)arg, &seek_tmp, sizeof(struct fm_seek_t))) {
+            WCN_DBG(FM_ERR | MAIN, "seek new copy_to_user error\n");
+            ret = -EFAULT;
+            goto out;
+        }
+        
+        break;
+    }
+    
+    case FM_IOCTL_SCAN_NEW: {
+        struct fm_scan_t tmp;
+        
+        WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_SCAN_NEW\n");
+
+        if (copy_from_user(&tmp, (void*)arg, sizeof(struct fm_scan_t))) {
+            WCN_DBG(FM_ERR | MAIN, "copy_from_user error\n");
+            ret =  -EFAULT;
+            goto out;
+        }
+
+        switch (tmp.cmd) {
+            case FM_SCAN_CMD_START: 
+                if ((tmp.upper > 10800) || (tmp.lower < 7600) || (tmp.space < 5) || (tmp.space > 20)) {
+                    WCN_DBG(FM_ERR | MAIN, "scan para error\n");
+                    ret = -EFAULT;
+                    goto out;
+                }
+                parm.cmd = tmp.cmd;
+                parm.lower = tmp.lower;
+                parm.upper = tmp.upper;
+                parm.space = tmp.space;
+
+                ret = fm_scan_new(fm, &parm);
+                if (ret < 0) {
+                    goto out;
+                }
+                break;
+                
+            case FM_SCAN_CMD_GET_CH_RSSI:
+                if (parm.sr_size && parm.sr.ch_rssi_buf) {
+                    if (copy_to_user(tmp.sr.ch_rssi_buf, parm.sr.ch_rssi_buf, parm.num * sizeof(struct fm_ch_rssi))) {
+                        WCN_DBG(FM_ERR | MAIN, "scan copy_to_user err\n");
+                        ret = -EFAULT;
+                        goto out;
+                    }
+                }
+                break;
+                
+            default:
+                break;
+        }
+
+        tmp.num = parm.num;
+        if (copy_to_user((void*)arg, &tmp, sizeof(struct fm_scan_t))) {
+            WCN_DBG(FM_ERR | MAIN, "copy_to_user error\n");
+            ret = -EFAULT;
+            goto out;
+        }
+        break;
+    }   
+    
+    case FM_IOCTL_CQI_GET: {
+        struct fm_cqi_req cqi_req;
+        fm_s8 *buf = NULL;
+        fm_s32 tmp;
+
+        WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_CQI_GET\n");
+
+        if (copy_from_user(&cqi_req, (void*)arg, sizeof(struct fm_cqi_req))) {
+            WCN_DBG(FM_ALT | MAIN, "copy_from_user failed\n");
+            ret = -EFAULT;
+            goto out;
+        }
+
+        if ((cqi_req.ch_num*sizeof(struct fm_cqi) > cqi_req.buf_size) || !cqi_req.cqi_buf) {
+            ret = -FM_EPARA;
+            goto out;
+        }
+
+        tmp = cqi_req.ch_num / 16 + ((cqi_req.ch_num % 16) ? 1 : 0);
+        tmp = tmp * 16 * sizeof(struct fm_cqi);
+        buf = fm_zalloc(tmp);
+
+        if (!buf) {
+            ret = -FM_ENOMEM;
+            goto out;
+        }
+
+        ret = fm_cqi_get(fm, cqi_req.ch_num, buf, tmp);
+
+        if (ret) {
+            fm_free(buf);
+            WCN_DBG(FM_ALT | MAIN, "get cqi failed\n");
+            goto out;
+        }
+
+        if (copy_to_user((void*)cqi_req.cqi_buf, buf, cqi_req.ch_num*sizeof(struct fm_cqi))) {
+            fm_free(buf);
+            ret = -EFAULT;
+            goto out;
+        }
+
+        fm_free(buf);
+        break;
+    }
+
+    case FM_IOCTL_GET_HW_INFO: {
+        struct fm_hw_info info;
+
+        WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_GET_HW_INFO\n");
+
+        ret = fm_get_hw_info(fm, &info);
+
+        if (ret) {
+            WCN_DBG(FM_ALT | MAIN, "get hw info failed\n");
+            goto out;
+        }
+
+        if (copy_to_user((void*)arg, &info, sizeof(struct fm_hw_info))) {
+            ret = -EFAULT;
+            goto out;
+        }
+
+        break;
+    }
+
+    case FM_IOCTL_GET_I2S_INFO: {
+        struct fm_i2s_info i2sinfo;
+
+        WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_GET_I2S_INFO\n");
+
+        ret = fm_get_i2s_info(fm, &i2sinfo);
+
+        if (ret) {
+            WCN_DBG(FM_ALT | MAIN, "get i2s info failed\n");
+            goto out;
+        }
+
+        if (copy_to_user((void*)arg, &i2sinfo, sizeof(struct fm_i2s_info))) {
+            ret = -EFAULT;
+            goto out;
+        }
+
+        break;
+    }
+
+    case FM_IOCTL_SETVOL: {
+        fm_u32 vol;
+
+        WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_SETVOL start\n");
+        if (copy_from_user(&vol, (void*)arg, sizeof(fm_u32))) {
+            WCN_DBG(FM_ALT | MAIN, "copy_from_user failed\n");
+            ret = -EFAULT;
+            goto out;
+        }
+
+        ret = fm_setvol(fm, vol);
+        WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_SETVOL end:%d\n", vol);
+        break;
+    }
+    case FM_IOCTL_GETVOL: {
+        fm_u32 vol;
+        WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_GETVOL start\n");
+        ret = fm_getvol(fm, &vol);
+        if (ret < 0) goto out;
+
+        if (copy_to_user((void*)arg, &vol, sizeof(fm_u32))) {
+            ret = -EFAULT;
+            goto out;
+        }
+
+        WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_GETVOL end=%d\n",vol);
+        break;
+    }
+
+    case FM_IOCTL_MUTE: {
+        fm_u32 bmute;
+
+        WCN_DBG(FM_NTC| MAIN, "FM_IOCTL_MUTE start\n");
+        if (copy_from_user(&bmute, (void*)arg, sizeof(fm_u32))) {
+            ret = -EFAULT;
+            goto out;
+        }
+
+        ret = fm_mute(fm, bmute);
+        WCN_DBG(FM_NTC| MAIN, "FM_IOCTL_MUTE end-%d\n", bmute);
+        break;
+    }
+
+    case FM_IOCTL_GETRSSI: {
+        fm_s32 rssi = 0;
+
+        ret = fm_getrssi(fm, &rssi);
+        if (ret < 0) goto out;
+
+        if (copy_to_user((void*)arg, &rssi, sizeof(fm_s32))) {
+            ret = -EFAULT;
+            goto out;
+        }
+
+        WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_GETRSSI:%d\n",rssi);
+        break;
+    }
+
+    case FM_IOCTL_RW_REG: {
+        struct fm_ctl_parm parm_ctl;
+        WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_RW_REG\n");
+
+        if (copy_from_user(&parm_ctl, (void*)arg, sizeof(struct fm_ctl_parm))) {
+            ret = -EFAULT;
+            goto out;
+        }
+
+        if (parm_ctl.rw_flag == 0) {
+            ret = fm_reg_write(fm, parm_ctl.addr, parm_ctl.val);
+        } else {
+            ret = fm_reg_read(fm, parm_ctl.addr, &parm_ctl.val);
+        }
+        if (ret < 0) goto out;
+
+        if ((parm_ctl.rw_flag == 0x01) && (!ret)) {
+            if (copy_to_user((void*)arg, &parm_ctl, sizeof(struct fm_ctl_parm))) {
+                ret = -EFAULT;
+                goto out;
+            }
+        }
+
+        break;
+    }
+
+    case FM_IOCTL_GETCHIPID: {
+        fm_u16 chipid;
+
+        ret = fm_chipid_get(fm, &chipid);
+        WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_GETCHIPID:%04x\n", chipid);
+        if (ret < 0) goto out;
+
+        if (copy_to_user((void*)arg, &chipid, sizeof(fm_u16))) {
+            ret = -EFAULT;
+            goto out;
+        }
+        break;
+    }
+
+    case FM_IOCTL_GETMONOSTERO: {
+        fm_u16 usStereoMono;
+
+        ret = fm_monostereo_get(fm, &usStereoMono);
+        WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_GETMONOSTERO:%04x\n", usStereoMono);
+        if (ret < 0) goto out;
+
+        if (copy_to_user((void*)arg, &usStereoMono, sizeof(fm_u16))) {
+            ret = -EFAULT;
+            goto out;
+        }
+        break;
+    }
+
+    case FM_IOCTL_SETMONOSTERO: {
+        WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_SETMONOSTERO, %d\n", (fm_s32)arg);
+        ret = fm_monostereo_set(fm, (fm_s32)arg);
+        break;
+    }
+
+    case FM_IOCTL_GETCURPAMD: {
+        fm_u16 PamdLevl;
+
+        ret = fm_pamd_get(fm, &PamdLevl);
+        WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_GETCURPAMD:%d\n", PamdLevl);
+        if (ret < 0) goto out;
+
+        if (copy_to_user((void*)arg, &PamdLevl, sizeof(fm_u16)))
+            ret = -EFAULT;
+            goto out;
+
+        break;
+    }
+
+    case FM_IOCTL_GETCAPARRAY: {
+        fm_s32 ca;
+
+        ret = fm_caparray_get(fm, &ca);
+        WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_GETCAPARRAY:%d\n", ca);
+        if (ret < 0) goto out;
+
+        if (copy_to_user((void*)arg, &ca, sizeof(fm_s32))) {
+            ret = -EFAULT;
+            goto out;
+        }
+        break;
+    }
+
+    case FM_IOCTL_EM_TEST: {
+        struct fm_em_parm parm_em;
+
+        WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_EM_TEST\n");
+
+        if (copy_from_user(&parm_em, (void*)arg, sizeof(struct fm_em_parm))) {
+            ret = -EFAULT;
+            goto out;
+        }
+        ret = fm_em_test(fm, parm_em.group_idx, parm_em.item_idx, parm_em.item_value);
+        break;
+    }
+
+    case FM_IOCTL_RDS_SUPPORT: {
+        fm_s32 support = FM_RDS_ENABLE;
+        WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_RDS_SUPPORT\n");
+
+        if (copy_to_user((void*)arg, &support, sizeof(fm_s32))) {
+            ret = -EFAULT;
+            goto out;
+        }
+        break;
+    }
+
+    case FM_IOCTL_IS_FM_POWERED_UP: {
+        fm_u32 powerup;
+        WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_IS_FM_POWERED_UP");
+
+        if (fm->chipon && fm_pwr_state_get(fm)) {
+            powerup = 1;
+        } else {
+            powerup = 0;
+        }
+
+        if (copy_to_user((void*)arg, &powerup, sizeof(fm_u32))) {
+            ret = -EFAULT;
+            goto out;
+        }
+        break;
+    }
+
+    case FM_IOCTL_RDS_ONOFF: {
+        fm_u16 rdson_off = 0;
+        WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_RDS_ONOFF start\n");
+
+        if (copy_from_user(&rdson_off, (void*)arg, sizeof(fm_u16))) {
+            ret = -EFAULT;
+            goto out;
+        }
+        ret = fm_rds_onoff(fm, rdson_off);
+        WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_RDS_ONOFF end:%d\n",rdson_off);
+        break;
+    }
+
+    case FM_IOCTL_GETGOODBCNT: {
+        fm_u16 uGBLCNT = 0;
+
+        ret = fm_rds_good_bc_get(fm, &uGBLCNT);
+        WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_GETGOODBCNT:%d\n", uGBLCNT);
+        if (ret < 0) goto out;
+
+        if (copy_to_user((void*)arg, &uGBLCNT, sizeof(fm_u16))) {
+            ret = -EFAULT;
+            goto out;
+        }
+        break;
+    }
+
+    case FM_IOCTL_GETBADBNT: {
+        fm_u16 uBadBLCNT = 0;
+
+        ret = fm_rds_bad_bc_get(fm, &uBadBLCNT);
+        WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_GETBADBNT:%d\n", uBadBLCNT);
+        if (ret < 0) goto out;
+
+        if (copy_to_user((void*)arg, &uBadBLCNT, sizeof(fm_u16))) {
+            ret = -EFAULT;
+            goto out;
+        }
+        break;
+    }
+
+    case FM_IOCTL_GETBLERRATIO: {
+        fm_u16 uBlerRatio = 0;
+
+        ret = fm_rds_bler_ratio_get(fm, &uBlerRatio);
+        WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_GETBLERRATIO:%d\n", uBlerRatio);
+        if (ret < 0) goto out;
+
+        if (copy_to_user((void*)arg, &uBlerRatio, sizeof(fm_u16))) {
+            ret = -EFAULT;
+            goto out;
+        }
+        break;
+    }
+
+    case FM_IOCTL_ANA_SWITCH: {
+        fm_s32 antenna = -1;
+        WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_ANA_SWITCH\n");
+
+        if (copy_from_user(&antenna, (void*)arg, sizeof(fm_s32))) {
+            WCN_DBG(FM_ALT | MAIN, "copy from user error\n");
+            ret = -EFAULT;
+            goto out;
+        }
+
+        ret = fm_ana_switch(fm, antenna);
+        break;
+    }
+
+    case FM_IOCTL_RDS_GROUPCNT: {
+        struct rds_group_cnt_req_t gc_req;
+        WCN_DBG(FM_DBG | MAIN, "......FM_IOCTL_RDS_GROUPCNT......\n");
+
+        if (copy_from_user(&gc_req, (void*)arg, sizeof(struct rds_group_cnt_req_t))) {
+            WCN_DBG(FM_ALT | MAIN, "copy_from_user error\n");
+            ret = -EFAULT;
+            goto out;
+        }
+
+        //handle group counter request
+        switch (gc_req.op) {
+        case RDS_GROUP_CNT_READ:
+            ret = fm_rds_group_cnt_get(fm, &gc_req.gc);
+            break;
+        case RDS_GROUP_CNT_WRITE:
+            break;
+        case RDS_GROUP_CNT_RESET:
+            ret = fm_rds_group_cnt_reset(fm);
+            break;
+        default:
+            break;
+        }
+
+        if (copy_to_user((void*)arg, &gc_req, sizeof(struct rds_group_cnt_req_t))) {
+            WCN_DBG(FM_ALT | MAIN, "copy_to_user error\n");
+            ret = -EFAULT;
+            goto out;
+        }
+
+        break;
+    }
+
+    case FM_IOCTL_RDS_GET_LOG: {
+        struct rds_raw_t rds_log;
+        fm_s32 len;
+        WCN_DBG(FM_DBG | MAIN, "......FM_IOCTL_RDS_GET_LOG......\n");
+        //fetch a record form RDS log buffer
+        ret = fm_rds_log_get(fm, (struct rds_rx_t*) & (rds_log.data), &len);
+        rds_log.dirty = TRUE;
+        rds_log.len = (len < sizeof(rds_log.data)) ? len : sizeof(rds_log.data);
+        if (ret < 0) goto out;
+
+        if (copy_to_user((void*)arg, &rds_log, rds_log.len + 2*sizeof(fm_s32))) {
+            WCN_DBG(FM_ALT | MAIN, "copy_to_user error\n");
+            ret = -EFAULT;
+            goto out;
+        }
+
+        break;
+    }
+
+    case FM_IOCTL_RDS_BC_RST: {
+        WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_RDS_BC_RST\n");
+        ret = fm_rds_block_cnt_reset(fm);
+        break;
+    }
+
+    case FM_IOCTL_I2S_SETTING: {
+        struct fm_i2s_setting i2s_cfg;
+        WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_I2S_SETTING\n");
+
+        if (copy_from_user(&i2s_cfg, (void*)arg, sizeof(struct fm_i2s_setting))) {
+            WCN_DBG(FM_ALT | MAIN, "i2s set, copy_from_user err\n");
+            ret = -EFAULT;
+            goto out;
+        }
+
+        ret = fm_i2s_set(fm, i2s_cfg.onoff, i2s_cfg.mode, i2s_cfg.sample);
+
+        if (ret) {
+            WCN_DBG(FM_ALT | MAIN, "Set i2s err\n");
+            goto out;
+        }
+
+        break;
+    }
+
+    case FM_IOCTL_IS_DESE_CHAN: {
+        fm_s32 tmp;
+        WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_IS_DESE_CHAN\n");
+
+        if (copy_from_user(&tmp, (void*)arg, sizeof(fm_s32))) {
+            WCN_DBG(FM_ALT | MAIN, "is dese chan, copy_from_user err\n");
+            ret = -EFAULT;
+            goto out;
+        }
+
+        tmp = fm_is_dese_chan(fm, (fm_u16)tmp);
+
+        if (copy_to_user((void*)arg, &tmp, sizeof(fm_s32))) {
+            WCN_DBG(FM_ALT | MAIN, "is dese chan, copy_to_user err\n");
+            ret = -EFAULT;
+            goto out;
+        }
+
+        break;
+    }
+    case FM_IOCTL_DESENSE_CHECK: 
+    {
+        fm_desense_check_t tmp;
+        WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_IS_DESE_CHAN\n");
+
+        if (copy_from_user(&tmp, (void*)arg, sizeof(fm_desense_check_t))) 
+        {
+            WCN_DBG(FM_ALT | MAIN, "desene check, copy_from_user err\n");
+            ret = -EFAULT;
+            goto out;
+        }
+        ret = fm_desense_check(fm, (fm_u16)tmp.freq,tmp.rssi);
+
+        /*if (copy_to_user((void*)arg, &tmp, sizeof(fm_desense_check_t))) {
+            WCN_DBG(FM_ALT | MAIN, "desene check, copy_to_user err\n");
+            ret = -EFAULT;
+            goto out;
+        }*/
+
+        break;
+    }
+       case FM_IOCTL_SCAN_GETRSSI:
+       {
+               /*struct fm_rssi_req *req;
+        WCN_DBG(FM_DBG | MAIN, "FM_IOCTL_SCAN_GETRSSI\n");
+               if(!(req = fm_vmalloc(sizeof(struct fm_rssi_req))))
+               {
+            WCN_DBG(FM_ALT | MAIN, "fm_vmalloc err\n");
+            ret = -EFAULT;
+            goto out;
+               }
+               if(copy_from_user(req, (void*)arg, sizeof(struct fm_rssi_req)))
+               {
+            WCN_DBG(FM_ALT | MAIN, "copy_from_user err\n");
+            ret = -EFAULT;
+                       fm_vfree(req);
+            goto out;
+               }
+               ret = fm_get_rssi_after_scan(fm, req);
+               if(-ERR_FW_NORES == ret){
+            WCN_DBG(FM_ALT | MAIN, "fm_get_rssi_after_scan err\n");
+               }
+               if(copy_to_user((void*)arg, req, sizeof(struct fm_rssi_req)))
+               {
+            WCN_DBG(FM_ALT | MAIN, "copy_to_user err\n");
+            ret = -EFAULT;
+                       fm_vfree(req);
+            goto out;
+               }
+               */
+        WCN_DBG(FM_ALT | MAIN, "FM_IOCTL_SCAN_GETRSSI:not support\n");
+               break;
+       }
+
+       case FM_IOCTL_DUMP_REG:
+       {
+               WCN_DBG(FM_NTC | MAIN,"......FM_IOCTL_DUMP_REG......\n");
+
+               ret = fm_dump_reg();
+               if(ret)
+               {
+                       WCN_DBG(FM_ALT | MAIN, "fm_dump_reg err\n");
+               }
+               break;
+       }
+       case FM_IOCTL_GPS_RTC_DRIFT:{
+               struct fm_gps_rtc_info rtc_info;
+               WCN_DBG(FM_NTC | MAIN,"......FM_IOCTL_GPS_RTC_DRIFT......\n");
+       
+               if (fm_false == fm->chipon){
+                       WCN_DBG(FM_ERR | MAIN,"ERROR, FM chip is OFF\n");
+            ret = -EFAULT;
+            goto out;
+               }
+               if(copy_from_user(&rtc_info, (void*)arg, sizeof(struct fm_gps_rtc_info))){
+                       WCN_DBG(FM_ERR | MAIN,"copy_from_user error\n");
+            ret = -EFAULT;
+            goto out;
+               }
+               
+               ret = fm_get_gps_rtc_info(&rtc_info);
+               if(ret){
+                       WCN_DBG(FM_ERR | MAIN,"fm_get_gps_rtc_info error\n");
+            goto out;
+               }
+               break;
+       }
+       case FM_IOCTL_OVER_BT_ENABLE:
+       {
+               fm_s32 fm_via_bt = -1;
+               WCN_DBG(FM_NTC | MAIN,"......FM_IOCTL_OVER_BT_ENABLE......\n");
+               
+               if(copy_from_user(&fm_via_bt, (void*)arg, sizeof(int32_t))){
+                       WCN_DBG(FM_ERR | MAIN,"copy_from_user error\n");
+                       ret = -EFAULT;
+                       goto out;
+               }
+       
+               ret = fm_over_bt(fm, fm_via_bt);
+               if(ret)
+               {
+                       WCN_DBG(FM_ERR | MAIN, "fm_over_bt err\n");
+               }
+               break;
+       }
+       
+    /***************************FM Tx function************************************/
+       case FM_IOCTL_TX_SUPPORT:
+       {
+               fm_s32 tx_support = -1;
+               WCN_DBG(FM_NTC | MAIN,"......FM_IOCTL_TX_SUPPORT......\n");
+
+               ret = fm_tx_support(fm,&tx_support);
+               if(ret)
+               {
+                       WCN_DBG(FM_ERR | MAIN, "fm_tx_support err\n");
+               }
+               if (copy_to_user((void*)arg, &tx_support, sizeof(fm_s32)))
+               {
+                       WCN_DBG(FM_ERR | MAIN,"copy_to_user error\n");
+                       ret = -EFAULT;
+                       goto out;
+               }
+               break;
+       }
+       case FM_IOCTL_POWERUP_TX:
+       {
+               struct fm_tune_parm parm;
+        WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_POWERUP_TX:0\n");
+        if (copy_from_user(&parm, (void*)arg, sizeof(struct fm_tune_parm))) {
+            ret = -EFAULT;
+            goto out;
+        }
+
+               ret = fm_powerup_tx(fm, &parm);
+        if (ret < 0) {
+            goto out;
+        }
+        ret = fm_tune_tx(fm, &parm);
+        if (ret < 0) goto out;
+
+        if (copy_to_user((void*)arg, &parm, sizeof(struct fm_tune_parm))) {
+            ret = -EFAULT;
+            goto out;
+        }
+        WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_POWERUP_TX:1\n");
+               break;
+       }
+       
+       case FM_IOCTL_TUNE_TX:
+       {
+               struct fm_tune_parm parm;
+        WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_TUNE_TX:0\n");
+
+        if (copy_from_user(&parm, (void*)arg, sizeof(struct fm_tune_parm))) {
+            ret = -EFAULT;
+            goto out;
+        }
+
+        ret = fm_tune_tx(fm, &parm);
+        if (ret < 0) {
+            goto out;
+        }
+
+        if (copy_to_user((void*)arg, &parm, sizeof(struct fm_tune_parm))) {
+            ret = -EFAULT;
+            goto out;
+        }
+
+               WCN_DBG(FM_NTC | MAIN, "FM_IOCTL_TUNE_TX:1\n");
+               break;
+       }
+       case FM_IOCTL_RDSTX_SUPPORT:
+       {
+               fm_s32 rds_tx_support = -1;
+               WCN_DBG(FM_NTC | MAIN,"......FM_IOCTL_RDSTX_SUPPORT......\n");
+
+               ret = fm_rdstx_support(fm,&rds_tx_support);
+               if(ret)
+               {
+                       WCN_DBG(FM_ERR | MAIN, "fm_rdstx_support err\n");
+               }
+               if (copy_to_user((void*)arg, &rds_tx_support, sizeof(fm_s32)))
+               {
+                       WCN_DBG(FM_ERR | MAIN,"copy_to_user error\n");
+                       ret = -EFAULT;
+                       goto out;
+               }
+               break;
+       }       
+       
+       case FM_IOCTL_RDSTX_ENABLE:
+       {
+               fm_s32 rds_tx_enable = -1;
+               WCN_DBG(FM_NTC | MAIN,"......FM_IOCTL_RDSTX_ENABLE......\n");
+
+               ret = fm_rdstx_enable(fm,&rds_tx_enable);
+               if(ret)
+               {
+                       WCN_DBG(FM_ERR | MAIN, "fm_rdstx_enable err\n");
+               }
+               if (copy_to_user((void*)arg, &rds_tx_enable, sizeof(fm_s32)))
+               {
+                       WCN_DBG(FM_ERR | MAIN,"copy_to_user error\n");
+                       ret = -EFAULT;
+                       goto out;
+               }
+               break;
+       }       
+       
+       case FM_IOCTL_RDS_TX:
+       {
+               struct fm_rds_tx_parm parm;
+               WCN_DBG(FM_NTC | MAIN, "......FM_IOCTL_RDS_TX......\n");
+
+               if (copy_from_user(&parm, (void*)arg, sizeof(struct fm_rds_tx_parm)))
+               {
+            WCN_DBG(FM_ALT | MAIN, "RDS Tx, copy_from_user err\n");
+                       ret = -EFAULT;
+                       goto out;
+               }
+
+               ret = fm_rds_tx(fm, &parm);
+               if(ret)
+               {
+            WCN_DBG(FM_ALT | MAIN, "fm_rds_tx err\n");
+               }
+
+               if (copy_to_user((void*)arg, &parm, sizeof(struct fm_rds_tx_parm))){
+            WCN_DBG(FM_ALT | MAIN, "RDS Tx, copy_to_user err\n");
+                       ret = -EFAULT;
+                       goto out;
+               }
+               break;
+       }
+       
+       case FM_IOCTL_TX_SCAN:
+       {
+               struct fm_tx_scan_parm parm;
+               WCN_DBG(FM_NTC | MAIN, "......FM_IOCTL_TX_SCAN......\n");
+
+               if (copy_from_user(&parm, (void*)arg, sizeof(struct fm_tx_scan_parm))){
+                       WCN_DBG(FM_ALT | MAIN,"copy_from_user error\n");
+                       ret = -EFAULT;
+                       goto out;
+               }
+               ret = fm_tx_scan(fm, &parm);
+               if(ret < 0){
+                       WCN_DBG(FM_ERR | MAIN,"FM_IOCTL_TX_SCAN failed\n");
+               }
+               if (copy_to_user((void*)arg, &parm, sizeof(struct fm_tx_scan_parm))){
+                       WCN_DBG(FM_ALT | MAIN,"copy_to_user error\n");
+                       ret = -EFAULT;
+                       goto out;
+               }
+               break;
+       }
+
+    default:
+        ret = -EPERM;
+    }
+
+out:
+    if (ret == -FM_EFW) {
+        // subsystem reset
+        fm_subsys_reset(fm);
+    }
+
+    return ret;
+}
+
+static loff_t fm_ops_lseek(struct file *filp, loff_t off, fm_s32 whence)
+{
+    struct fm *fm = filp->private_data;
+
+    if (whence == SEEK_END) {
+        fm_hwscan_stop(fm);
+    } else if (whence == SEEK_SET) {
+        FM_EVENT_SEND(fm->rds_event, FM_RDS_DATA_READY);
+    }
+
+    return off;
+}
+
+static ssize_t fm_ops_read(struct file *filp, char *buf, size_t len, loff_t *off)
+{
+    struct fm *fm = filp->private_data;
+    fm_s32 copy_len = 0;
+
+    if (!fm) {
+        WCN_DBG(FM_ALT | MAIN, "fm_read invalid fm pointer\n");
+        return 0;
+    }
+
+    if (!buf || len < sizeof(rds_t)) {
+        WCN_DBG(FM_DBG | MAIN, "fm_read invliad buf\n");
+        return 0;
+    }
+
+    //block when FM is resetting
+    while (fm_sys_state_get(fm) != FM_SUBSYS_RST_OFF) {
+        msleep_interruptible(100);
+    }
+
+    copy_len = sizeof(rds_t);
+
+    return fm_rds_read(fm, buf, copy_len);
+}
+
+static fm_s32 fm_ops_open(struct inode *inode, struct file *filp)
+{
+    fm_s32 ret = 0;
+    struct fm_platform *plat = container_of(inode->i_cdev, struct fm_platform, cdev);
+    struct fm *fm = container_of(plat, struct fm, platform);
+
+    WCN_DBG(FM_NTC | MAIN, "fm_ops_open:0\n");
+    if (fm_sys_state_get(fm) != FM_SUBSYS_RST_OFF) {
+        WCN_DBG(FM_ALT| MAIN, "FM subsys is resetting, retry later\n");
+        ret = -FM_ESRST;
+        return ret;
+    }
+    
+    ret = fm_open(fm);
+    filp->private_data = fm;
+
+    WCN_DBG(FM_NTC | MAIN, "fm_ops_open:1\n");
+    return ret;
+}
+
+static fm_s32 fm_ops_release(struct inode *inode, struct file *filp)
+{
+//    fm_s32 ret = 0;
+//    struct fm_platform *plat = container_of(inode->i_cdev, struct fm_platform, cdev);
+//    struct fm *fm = container_of(plat, struct fm, platform);
+
+//    WCN_DBG(FM_NTC | MAIN, "fm_ops_release:0\n");
+    //fm_close(fm);
+    filp->private_data = NULL;
+
+    WCN_DBG(FM_NTC | MAIN, "fm_ops_release\n");
+    return 0;
+}
+
+static fm_s32 fm_ops_flush(struct file *filp,fl_owner_t Id)
+{
+    fm_s32 ret = 0;
+    struct fm *fm = filp->private_data;
+
+    WCN_DBG(FM_NTC | MAIN, "fm_ops_flush:0\n");
+    fm_close(fm);
+    filp->private_data = fm;
+
+    WCN_DBG(FM_NTC | MAIN, "fm_ops_flush:1\n");
+    return ret;
+}
+
+static fm_s32 fm_proc_read(char *page, char **start, off_t off, fm_s32 count, fm_s32 *eof, void *data)
+{
+    fm_s32 cnt = 0;
+    struct fm *fm  = g_fm;
+
+    WCN_DBG(FM_NTC | MAIN, "Enter fm_proc_read.\n");
+
+    if (off != 0)
+        return 0;
+
+    if (!fm) {
+        WCN_DBG(FM_ALT | MAIN, "para err\n");
+        return 0;
+    }
+
+    if (fm->chipon && (fm_pwr_state_get(fm) == FM_PWR_RX_ON)) 
+       {
+        cnt = sprintf(page, "1\n");
+               WCN_DBG(FM_NTC | MAIN, " FM_PWR_RX_ON\n");
+    } 
+       else if (fm->chipon && (fm_pwr_state_get(fm) == FM_PWR_TX_ON)) 
+       {
+               WCN_DBG(FM_NTC | MAIN, " FM_PWR_TX_ON\n");
+        cnt = sprintf(page, "2\n");
+    } 
+       else 
+       {
+        cnt = sprintf(page, "0\n");
+    }
+
+    *eof = 1;
+    WCN_DBG(FM_NTC | MAIN, "Leave fm_proc_read. cnt = %d\n", cnt);
+    return cnt;
+}
+
+static fm_s32 fm_proc_write(struct file *file, const char *buffer, unsigned long count, void *data)
+{
+    fm_s8 tmp_buf[50] = {0};
+    fm_u32 copysize;
+
+    copysize = (count < (sizeof(tmp_buf) - 1)) ? count : (sizeof(tmp_buf) - 1);
+
+    WCN_DBG(FM_NTC | MAIN, "fm_proc_write:0\n");
+    if (copy_from_user(tmp_buf, buffer, copysize)) {
+        WCN_DBG(FM_ERR | MAIN, "failed copy_from_user\n");
+        return -EFAULT;
+    }
+
+    if (strncmp(tmp_buf, "subsys reset", strlen("subsys reset")) == 0) {
+        fm_subsys_reset(g_fm);
+        return count;
+    }
+    
+    if (!fm_cust_config_setup(tmp_buf)) {
+        WCN_DBG(FM_NTC | MAIN, "get config form %s ok\n", tmp_buf);
+        return count;
+    }
+
+    if (sscanf(tmp_buf, "%x", &g_dbg_level) != 1) {
+        WCN_DBG(FM_ERR | MAIN, "failed g_dbg_level = 0x%x\n", g_dbg_level);
+        return -EFAULT;
+    }
+
+    WCN_DBG(FM_NTC | MAIN, "fm_proc_write:1 g_dbg_level = 0x%x\n", g_dbg_level);
+    return count;
+}
+
+#define FM_DEV_STATIC_ALLOC
+#define FM_DEV_MAJOR    193
+static int FM_major = FM_DEV_MAJOR;      /* dynamic allocation */
+
+static fm_s32 fm_cdev_setup(struct fm *fm)
+{
+    fm_s32 ret = 0;
+    struct fm_platform *plat = &fm->platform;
+
+#ifdef FM_DEV_STATIC_ALLOC
+    /*static allocate chrdev*/
+    plat->dev_t = MKDEV(FM_major, 0);
+    ret = register_chrdev_region(plat->dev_t, 1, FM_NAME);
+
+    if (ret) {
+        WCN_DBG(FM_ERR | MAIN, "%s():fail to register chrdev\n", __func__);
+        return ret;
+    }
+
+#endif
+
+#ifndef FM_DEV_STATIC_ALLOC
+    ret = alloc_chrdev_region(&plat->dev_t, 0, 1, FM_NAME);
+
+    if (ret) {
+        WCN_DBG(FM_ALT | MAIN, "alloc dev_t failed\n");
+        return ret;
+    }
+
+#endif
+
+    WCN_DBG(FM_NTC | MAIN, "alloc %s:%d:%d\n", FM_NAME, MAJOR(plat->dev_t), MINOR(plat->dev_t));
+
+    cdev_init(&plat->cdev, &fm_ops);
+
+    plat->cdev.owner = THIS_MODULE;
+    plat->cdev.ops = &fm_ops;
+
+    ret = cdev_add(&plat->cdev, plat->dev_t, 1);
+
+    if (ret) {
+        WCN_DBG(FM_ALT | MAIN, "add dev_t failed\n");
+        return ret;
+    }
+
+#ifndef FM_DEV_STATIC_ALLOC
+    plat->cls = class_create(THIS_MODULE, FM_NAME);
+
+    if (IS_ERR(plat->cls)) {
+        ret = PTR_ERR(plat->cls);
+        WCN_DBG(FM_ALT | MAIN, "class_create err:%d\n", ret);
+        return ret;
+    }
+
+    plat->dev = device_create(plat->cls, NULL, plat->dev_t, NULL, FM_NAME);
+#endif
+
+    return ret;
+}
+
+static fm_s32  fm_cdev_destroy(struct fm *fm)
+{
+    FMR_ASSERT(fm);
+
+    device_destroy(fm->platform.cls, fm->platform.dev_t);
+    class_destroy(fm->platform.cls);
+    cdev_del(&fm->platform.cdev);
+    unregister_chrdev_region(fm->platform.dev_t, 1);
+
+    return 0;
+}
+
+static fm_s32 fm_mod_init(fm_u32 arg)
+{
+    fm_s32 ret = 0;
+    struct fm *fm = NULL;
+
+    fm = fm_dev_init(0);
+
+    if (!fm) {
+        ret = -ENOMEM;
+        goto ERR_EXIT;
+    }
+
+    if ((ret = fm_cdev_setup(fm))) {
+        goto ERR_EXIT;
+    }
+
+    //fm proc file create "/proc/fm"
+    g_fm_proc = create_proc_entry(FM_PROC_FILE, 0444, NULL);
+
+    if (g_fm_proc == NULL) {
+        WCN_DBG(FM_ALT | MAIN, "create_proc_entry failed\n");
+        ret = -ENOMEM;
+        goto ERR_EXIT;
+    } else {
+        g_fm_proc->read_proc = fm_proc_read;
+        g_fm_proc->write_proc = fm_proc_write;
+        WCN_DBG(FM_NTC | MAIN, "create_proc_entry success\n");
+    }
+
+    g_fm = fm;
+    return 0;
+
+ERR_EXIT:
+
+    if (fm) {
+        fm_cdev_destroy(fm);
+        fm_dev_destroy(fm);
+    }
+
+    remove_proc_entry(FM_PROC_FILE, NULL);
+    return ret;
+}
+
+static fm_s32 fm_mod_destroy(struct fm *fm)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(fm);
+
+    WCN_DBG(FM_NTC | MAIN, "%s\n", __func__);
+    remove_proc_entry(FM_PROC_FILE, NULL);
+    fm_cdev_destroy(fm);
+    fm_dev_destroy(fm);
+
+    return ret;
+}
+
+static fm_s32 mt_fm_probe(struct platform_device *pdev)
+{
+    fm_s32 ret = 0;
+
+    WCN_DBG(FM_NTC | MAIN, "%s\n", __func__);
+
+    ret = fm_mod_init(0);
+
+    if (ret) {
+        WCN_DBG(FM_ERR | MAIN, "fm mod init err\n");
+        return -ENOMEM;
+    }
+
+    return ret;
+}
+
+static fm_s32 mt_fm_remove(struct platform_device *pdev)
+{
+    WCN_DBG(FM_NTC | MAIN, "%s\n", __func__);
+
+    fm_mod_destroy(g_fm);
+    g_fm = NULL;
+    return 0;
+}
+
+static struct platform_device mt_fm_device = {
+    .name      = FM_NAME,
+    .id        = -1,
+};
+
+//platform driver entry
+static struct platform_driver mt_fm_dev_drv = {
+    .probe   = mt_fm_probe,
+    .remove  = mt_fm_remove,
+    .driver = {
+        .name   = FM_NAME,
+        .owner  = THIS_MODULE,
+    }
+};
+
+static fm_s32 __init mt_fm_init(void)
+{
+    fm_s32 ret = 0;
+
+    ret = fm_env_setup();
+
+    if (ret) {
+        fm_env_destroy();
+        return ret;
+    }
+
+    //register fm device to platform bus
+    ret = platform_device_register(&mt_fm_device);
+
+    if (ret) {
+        return ret;
+    }
+
+    //register fm driver to platform bus
+    ret = platform_driver_register(&mt_fm_dev_drv);
+
+    if (ret) {
+        return ret;
+    }
+
+    WCN_DBG(FM_NTC | MAIN, "6. fm platform driver registered\n");
+    return ret;
+}
+
+static void __exit mt_fm_exit(void)
+{
+    platform_driver_unregister(&mt_fm_dev_drv);
+    fm_env_destroy();
+}
+
+
+EXPORT_SYMBOL(g_dbg_level);
+module_init(mt_fm_init);
+module_exit(mt_fm_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("MediaTek FM Driver");
+MODULE_AUTHOR("Hongcheng <hongcheng.xia@MediaTek.com>");
diff --git a/drivers/mtk_wcn_combo/drv_fm/core/fm_patch.c b/drivers/mtk_wcn_combo/drv_fm/core/fm_patch.c
new file mode 100755 (executable)
index 0000000..f69d3fc
--- /dev/null
@@ -0,0 +1,146 @@
+/* fm_patch.c
+ *
+ * (C) Copyright 2011
+ * MediaTek <www.MediaTek.com>
+ * Hongcheng <hongcheng.xia@MediaTek.com>
+ *
+ * FM Radio Driver -- patch functions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/fs.h>
+#include <asm/uaccess.h>
+
+#include "fm_typedef.h"
+#include "fm_dbg.h"
+#include "fm_err.h"
+
+/*
+ * fm_file_exist - test file
+ * @filename - source file name
+ * If exsit, return 0, else error code
+ */
+fm_s32 fm_file_exist(const fm_s8 *filename)
+{
+    fm_s32 ret = 0;
+    mm_segment_t old_fs;
+    struct file *fp = NULL;
+
+    old_fs = get_fs();
+    set_fs(KERNEL_DS);
+    fp = filp_open(filename, O_RDONLY, 0);
+
+    if (IS_ERR(fp)) {
+        WCN_DBG(FM_ERR | CHIP, "open \"%s\" failed\n", filename);
+        set_fs(old_fs);
+        return -FM_EPATCH;
+    } else {
+        WCN_DBG(FM_NTC | CHIP, "open \"%s\" ok\n", filename);
+    }
+
+    if (fp) {
+        filp_close(fp, NULL);
+    }
+
+    set_fs(old_fs);
+
+    return ret;
+}
+
+
+/*
+ * fm_file_read - read FM DSP patch/coeff/hwcoeff/rom binary file
+ * @filename - source file name
+ * @dst - target buffer
+ * @len - desired read length
+ * @position - the read position
+ * If success, return read length in bytes, else error code
+ */
+fm_s32 fm_file_read(const fm_s8 *filename, fm_u8* dst, fm_s32 len, fm_s32 position)
+{
+    fm_s32 ret = 0;
+    loff_t pos = position;
+    mm_segment_t old_fs;
+    struct file *fp = NULL;
+
+    old_fs = get_fs();
+    set_fs(KERNEL_DS);
+    fp = filp_open(filename, O_RDONLY, 0);
+
+    if (IS_ERR(fp)) {
+        WCN_DBG(FM_ERR | CHIP, "open \"%s\" failed\n", filename);
+        set_fs(old_fs);
+        return -FM_EPATCH;
+    } else {
+        WCN_DBG(FM_NTC | CHIP, "open \"%s\" ok\n", filename);
+    }
+
+    ret = vfs_read(fp, (char __user *)dst, len, &pos);
+
+    if (ret < 0) {
+        WCN_DBG(FM_ERR | CHIP, "read \"%s\" failed\n", filename);
+    } else if (ret < len) {
+        WCN_DBG(FM_NTC | CHIP, "read \"%s\" part data\n", filename);
+    } else {
+        WCN_DBG(FM_NTC | CHIP, "read \"%s\" full data\n", filename);
+    }
+
+    if (fp) {
+        filp_close(fp, NULL);
+    }
+
+    set_fs(old_fs);
+
+    return ret;
+}
+
+
+fm_s32 fm_file_write(const fm_s8 *filename, fm_u8* dst, fm_s32 len, fm_s32 *ppos)
+{
+    fm_s32 ret = 0;
+    loff_t pos = *ppos;
+    mm_segment_t old_fs;
+    struct file *fp = NULL;
+
+    old_fs = get_fs();
+    set_fs(KERNEL_DS);
+    fp = filp_open(filename, O_CREAT | O_RDWR, 0);
+
+    if (IS_ERR(fp)) {
+        WCN_DBG(FM_ERR | CHIP, "open \"%s\" failed\n", filename);
+        set_fs(old_fs);
+        return -FM_EPATCH;
+    } else {
+        WCN_DBG(FM_NTC | CHIP, "open \"%s\" ok\n", filename);
+    }
+
+    WCN_DBG(FM_NTC | CHIP, "\"%s\" old pos %d\n", filename, (int)pos);
+    ret = vfs_write(fp, (char __user *)dst, len, &pos);
+    WCN_DBG(FM_NTC | CHIP, "\"%s\" new pos %d\n", filename, (int)pos);
+    *ppos = pos;
+    if (ret < 0) {
+        WCN_DBG(FM_ERR | CHIP, "write \"%s\" failed\n", filename);
+    } else if (ret < len) {
+        WCN_DBG(FM_NTC | CHIP, "write \"%s\" data\n", filename);
+    } 
+
+    if (fp) {
+        filp_close(fp, NULL);
+    }
+
+    set_fs(old_fs);
+
+    return ret;
+}
diff --git a/drivers/mtk_wcn_combo/drv_fm/core/fm_rds_parser.c b/drivers/mtk_wcn_combo/drv_fm/core/fm_rds_parser.c
new file mode 100755 (executable)
index 0000000..e890243
--- /dev/null
@@ -0,0 +1,1867 @@
+/* fm_rds_parser.c
+ *
+ * (C) Copyright 2011
+ * MediaTek <www.MediaTek.com>
+ * hongcheng <hongcheng.xia@MediaTek.com>
+ *
+ * FM Radio Driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/string.h>
+
+#include "fm_typedef.h"
+#include "fm_rds.h"
+#include "fm_dbg.h"
+#include "fm_err.h"
+#include "fm_stdlib.h"
+
+//static rds_ps_state_machine_t ps_state_machine = RDS_PS_START;
+//static rds_rt_state_machine_t rt_state_machine = RDS_RT_START;
+struct fm_state_machine {
+    fm_s32 state;
+    fm_s32(*state_get)(struct fm_state_machine *thiz);
+    fm_s32(*state_set)(struct fm_state_machine *thiz, fm_s32 new_state);
+};
+
+static fm_s32 fm_state_get(struct fm_state_machine *thiz)
+{
+    return thiz->state;
+}
+
+static fm_s32 fm_state_set(struct fm_state_machine *thiz, fm_s32 new_state)
+{
+    return thiz->state = new_state;
+}
+
+#define STATE_SET(a, s)        \
+{                           \
+    if((a)->state_set){          \
+        (a)->state_set((a), (s));    \
+    }                       \
+}
+
+#define STATE_GET(a)         \
+({                             \
+    fm_s32 __ret = 0;              \
+    if((a)->state_get){          \
+        __ret = (a)->state_get((a));    \
+    }                       \
+    __ret;                  \
+})
+
+static fm_u16(*rds_get_freq)(void)  = NULL;
+
+//RDS spec related handle flow
+/*
+ * rds_cnt_get
+ * To get rds group count form raw data
+ * If success return 0, else return error code
+*/
+static fm_s32 rds_cnt_get(struct rds_rx_t *rds_raw, fm_s32 raw_size, fm_s32 *cnt)
+{
+    fm_s32 gap = sizeof(rds_raw->cos) + sizeof(rds_raw->sin);
+
+    FMR_ASSERT(rds_raw);
+    FMR_ASSERT(cnt);
+    *cnt = (raw_size - gap) / sizeof(rds_packet_t);
+    WCN_DBG(FM_INF | RDSC, "group cnt=%d\n", *cnt);
+
+    return 0;
+}
+
+/*
+ * rds_grp_get
+ * To get rds group[n] data form raw data with index
+ * If success return 0, else return error code
+*/
+static fm_s32 rds_grp_get(fm_u16 *dst, struct rds_rx_t *raw, fm_s32 idx)
+{
+    FMR_ASSERT(dst);
+    FMR_ASSERT(raw);
+
+    if (idx > (MAX_RDS_RX_GROUP_CNT - 1)) {
+        return -FM_EPARA;
+    }
+
+    dst[0] = raw->data[idx].blkA;
+    dst[1] = raw->data[idx].blkB;
+    dst[2] = raw->data[idx].blkC;
+    dst[3] = raw->data[idx].blkD;
+    dst[4] = raw->data[idx].crc;
+    dst[5] = raw->data[idx].cbc;
+
+    WCN_DBG(FM_NTC | RDSC, "BLOCK:%04x %04x %04x %04x, CRC:%04x CBC:%04x\n", dst[0], dst[1], dst[2], dst[3], dst[4], dst[5]);
+
+    return 0;
+}
+
+/*
+ * rds_checksum_check
+ * To check CRC rerult, if OK, *valid=fm_true, else *valid=fm_false
+ * If success return 0, else return error code
+*/
+static fm_s32 rds_checksum_check(fm_u16 crc, fm_s32 mask, fm_bool *valid)
+{
+    FMR_ASSERT(valid);
+
+    if ((crc & mask) == mask) {
+        *valid = fm_true;
+    } else {
+        *valid = fm_false;
+    }
+
+    return 0;
+}
+
+/*
+ * rds_cbc_get - To get block_n's correct bit count form cbc
+ * @cbc, the group's correct bit count
+ * @blk, target the block
+ *
+ * If success, return block_n's cbc, else error code
+*/
+/*
+static fm_s32 rds_cbc_get(fm_u16 cbc, enum rds_blk_t blk)
+{
+    int ret = 0;
+
+    switch (blk) {
+    case RDS_BLK_A:
+        ret = (cbc & 0xF000) >> 12;
+        break;
+    case RDS_BLK_B:
+        ret = (cbc & 0x0F00) >> 8;
+        break;
+    case RDS_BLK_C:
+        ret = (cbc & 0x00F0) >> 4;
+        break;
+    case RDS_BLK_D:
+        ret = (cbc & 0x000F) >> 0;
+        break;
+    default:
+        break;
+    }
+
+    WCN_DBG(FM_INF | RDSC, "group cbc=0x%04x\n", cbc);
+    return ret;
+}
+*/
+/*
+ * rds_event_set
+ * To set rds event, and user space can use this flag to juge which event happened
+ * If success return 0, else return error code
+*/
+static fm_s32 rds_event_set(fm_u16 *events, fm_s32 event_mask)
+{
+    FMR_ASSERT(events);
+       WCN_DBG(FM_NTC | RDSC, "rds set event[%x->%x]\n", event_mask,*events);
+    *events |= event_mask;
+
+    return 0;
+}
+
+/*
+ * rds_flag_set
+ * To set rds event flag, and user space can use this flag to juge which event happened
+ * If success return 0, else return error code
+*/
+static fm_s32 rds_flag_set(fm_u32 *flags, fm_s32 flag_mask)
+{
+    FMR_ASSERT(flags);
+    *flags |= flag_mask;
+       WCN_DBG(FM_NTC | RDSC, "rds set flag[%x->%x]\n", flag_mask,*flags);
+
+    return 0;
+}
+
+/*
+ * rds_grp_type_get
+ * To get rds group type form blockB
+ * If success return 0, else return error code
+*/
+static fm_s32 rds_grp_type_get(fm_u16 crc, fm_u16 blk, fm_u8 *type, fm_u8 *subtype)
+{
+    fm_bool valid = fm_false;
+
+    FMR_ASSERT(type);
+    FMR_ASSERT(subtype);
+    //to get the group type from block B
+    rds_checksum_check(crc, FM_RDS_GDBK_IND_B, &valid);
+
+    if (valid == fm_true) {
+        *type = (blk & 0xF000) >> 12; //Group type(4bits)
+        *subtype = (blk & 0x0800) >> 11; //version code(1bit), 0=vesionA, 1=versionB
+    } else {
+        WCN_DBG(FM_WAR | RDSC, "Block1 CRC err\n");
+        return -FM_ECRC;
+    }
+
+    WCN_DBG(FM_DBG | RDSC, "Type=%d, subtype:%s\n", (fm_s32)*type, *subtype ? "version B" : "version A");
+    return 0;
+}
+
+/*
+ * rds_grp_counter_add
+ * @type -- group type, rang: 0~15
+ * @subtype -- sub group type, rang:0~1
+ *
+ * add group counter, g0a~g15b
+ * we use type value as the index
+ * If success return 0, else return error code
+*/
+static fm_s32 rds_grp_counter_add(fm_u8 type, fm_u8 subtype, struct rds_group_cnt_t *gc)
+{
+    FMR_ASSERT(gc);
+
+    if (type > 15) {
+        return -FM_EPARA;
+    }
+
+    switch (subtype) {
+    case RDS_GRP_VER_A:
+        gc->groupA[type]++;
+        break;
+    case RDS_GRP_VER_B:
+        gc->groupB[type]++;
+        break;
+    default:
+        return -FM_EPARA;
+        break;
+    }
+
+    gc->total++;
+    WCN_DBG(FM_INF | RDSC, "group counter:%d\n", (fm_s32)gc->total);
+    return 0;
+}
+
+/*
+ * rds_grp_counter_get
+ *
+ * read group counter , g0a~g15b
+ * If success return 0, else return error code
+*/
+extern fm_s32 rds_grp_counter_get(struct rds_group_cnt_t *dst, struct rds_group_cnt_t *src)
+{
+    FMR_ASSERT(dst);
+    FMR_ASSERT(src);
+    fm_memcpy(dst, src, sizeof(struct rds_group_cnt_t));
+    WCN_DBG(FM_DBG | RDSC, "rds gc get[total=%d]\n", (fm_s32)dst->total);
+    return 0;
+}
+
+/*
+ * rds_grp_counter_reset
+ *
+ * clear group counter to 0, g0a~g15b
+ * If success return 0, else return error code
+*/
+extern fm_s32 rds_grp_counter_reset(struct rds_group_cnt_t *gc)
+{
+    FMR_ASSERT(gc);
+    fm_memset(gc, 0, sizeof(struct rds_group_cnt_t));
+    return 0;
+}
+
+extern fm_s32 rds_log_in(struct rds_log_t *thiz, struct rds_rx_t *new_log, fm_s32 new_len)
+{
+    FMR_ASSERT(new_log);
+
+    if (thiz->len < thiz->size) {
+        new_len = (new_len < sizeof(struct rds_rx_t)) ? new_len : sizeof(struct rds_rx_t);
+        fm_memcpy(&(thiz->rds_log[thiz->in]), new_log, new_len);
+        thiz->log_len[thiz->in] = new_len;
+        thiz->in = (thiz->in + 1) % thiz->size;
+        thiz->len++;
+        WCN_DBG(FM_DBG | RDSC, "add a new log[len=%d]\n", thiz->len);
+    } else {
+        WCN_DBG(FM_WAR | RDSC, "rds log buf is full\n");
+        return -FM_ENOMEM;
+    }
+
+    return 0;
+}
+
+extern fm_s32 rds_log_out(struct rds_log_t *thiz, struct rds_rx_t *dst, fm_s32 *dst_len)
+{
+    FMR_ASSERT(dst);
+    FMR_ASSERT(dst_len);
+
+    if (thiz->len > 0) {
+        *dst_len = thiz->log_len[thiz->out];
+        *dst_len = (*dst_len < sizeof(struct rds_rx_t)) ? *dst_len : sizeof(struct rds_rx_t);
+        fm_memcpy(dst, &(thiz->rds_log[thiz->out]), *dst_len);
+        thiz->out = (thiz->out + 1) % thiz->size;
+        thiz->len--;
+        WCN_DBG(FM_DBG | RDSC, "del a new log[len=%d]\n", thiz->len);
+    } else {
+        *dst_len = 0;
+        WCN_DBG(FM_WAR | RDSC, "rds log buf is empty\n");
+    }
+
+    return 0;
+}
+
+/*
+ * rds_grp_pi_get
+ * To get rds group pi code form blockA
+ * If success return 0, else return error code
+*/
+static fm_s32 rds_grp_pi_get(fm_u16 crc, fm_u16 blk, fm_u16 *pi, fm_bool *dirty)
+{
+    fm_s32 ret = 0;
+    fm_bool valid = fm_false;
+
+    FMR_ASSERT(pi);
+    FMR_ASSERT(dirty);
+
+    //to get the group pi code from block A
+    ret = rds_checksum_check(crc, FM_RDS_GDBK_IND_A, &valid);
+
+    if (valid == fm_true) {
+        if (*pi != blk) {
+            //PI=program Identication
+            *pi = blk;
+            *dirty = fm_true; // yes, we got new PI code
+        } else {
+            *dirty = fm_false; // PI is the same as last one
+        }
+    } else {
+        WCN_DBG(FM_WAR | RDSC, "Block0 CRC err\n");
+        return -FM_ECRC;
+    }
+
+    WCN_DBG(FM_INF | RDSC, "PI=0x%04x, %s\n", *pi, *dirty ? "new" : "old");
+    return ret;
+}
+
+/*
+ * rds_grp_pty_get
+ * To get rds group pty code form blockB
+ * If success return 0, else return error code
+*/
+static fm_s32 rds_grp_pty_get(fm_u16 crc, fm_u16 blk, fm_u8 *pty, fm_bool *dirty)
+{
+    fm_s32 ret = 0;
+//    fm_bool valid = fm_false;
+
+    FMR_ASSERT(pty);
+    FMR_ASSERT(dirty);
+
+    //to get PTY code from block B
+//    ret = rds_checksum_check(crc, FM_RDS_GDBK_IND_B, &valid);
+
+//    if (valid == fm_false) {
+//        WCN_DBG(FM_WAR | RDSC, "Block1 CRC err\n");
+//        return -FM_ECRC;
+//    }
+
+    if (*pty != ((blk & 0x03E0) >> 5)) {
+        //PTY=Program Type Code
+        *pty = (blk & 0x03E0) >> 5;
+        *dirty = fm_true; // yes, we got new PTY code
+    } else {
+        *dirty = fm_false; // PTY is the same as last one
+    }
+
+    WCN_DBG(FM_INF | RDSC, "PTY=%d, %s\n", (fm_s32)*pty, *dirty ? "new" : "old");
+    return ret;
+}
+
+/*
+ * rds_grp_tp_get
+ * To get rds group tp code form blockB
+ * If success return 0, else return error code
+*/
+static fm_s32 rds_grp_tp_get(fm_u16 crc, fm_u16 blk, fm_u8 *tp, fm_bool *dirty)
+{
+    fm_s32 ret = 0;
+//    fm_bool valid = fm_false;
+
+    FMR_ASSERT(tp);
+    FMR_ASSERT(dirty);
+
+    //to get TP code from block B
+//    ret = rds_checksum_check(crc, FM_RDS_GDBK_IND_B, &valid);
+
+//    if (valid == fm_false) {
+//        WCN_DBG(FM_WAR | RDSC, "Block1 CRC err\n");
+//        return -FM_ECRC;
+//    }
+
+    if (*tp != ((blk&0x0400) >> 10)) {
+        //Tranfic Program Identification
+        *tp = (blk & 0x0400) >> 10;
+        *dirty = fm_true; // yes, we got new TP code
+    } else {
+        *dirty = fm_false; // TP is the same as last one
+    }
+
+    WCN_DBG(FM_NTC | RDSC, "TP=%d, %s\n", (fm_s32)*tp, *dirty ? "new" : "old");
+    return ret;
+}
+
+/*
+ * rds_g0_ta_get
+ * To get rds group ta code form blockB
+ * If success return 0, else return error code
+*/
+static fm_s32 rds_g0_ta_get(fm_u16 blk, fm_u8 *ta, fm_bool *dirty)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(ta);
+    FMR_ASSERT(dirty);
+
+    //TA=Traffic Announcement code
+    if (*ta != ((blk & 0x0010) >> 4)) {
+        *ta = (blk & 0x0010) >> 4;
+        *dirty = fm_true; // yes, we got new TA code
+    } else {
+        *dirty = fm_false; // TA is the same as last one
+    }
+
+    WCN_DBG(FM_INF | RDSC, "TA=%d, %s\n", (fm_s32)*ta, *dirty ? "new" : "old");
+    return ret;
+}
+
+/*
+ * rds_g0_music_get
+ * To get music-speech switch code form blockB
+ * If success return 0, else return error code
+*/
+static fm_s32 rds_g0_music_get(fm_u16 blk, fm_u8 *music, fm_bool *dirty)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(music);
+    FMR_ASSERT(dirty);
+
+    //M/S=music speech switch code
+    if (*music != ((blk & 0x0008) >> 3)) {
+        *music = (blk & 0x0008) >> 3;
+        *dirty = fm_true; // yes, we got new music code
+    } else {
+        *dirty = fm_false; // music  is the same as last one
+    }
+
+    WCN_DBG(FM_INF | RDSC, "Music=%d, %s\n", (fm_s32)*music, *dirty ? "new" : "old");
+    return ret;
+}
+
+/*
+ * rds_g0_ps_addr_get
+ * To get ps addr form blockB, blkB b0~b1
+ * If success return 0, else return error code
+*/
+static fm_s32 rds_g0_ps_addr_get(fm_u16 blkB, fm_u8 *addr)
+{
+    FMR_ASSERT(addr);
+    *addr = (fm_u8)blkB & 0x03;
+
+    WCN_DBG(FM_INF | RDSC, "addr=0x%02x\n", *addr);
+    return 0;
+}
+
+/*
+ * rds_g0_di_flag_get
+ * To get DI segment flag form blockB, blkB b2
+ * If success return 0, else return error code
+*/
+static fm_s32 rds_g0_di_flag_get(fm_u16 blkB, fm_u8 *flag)
+{
+    FMR_ASSERT(flag);
+    *flag = (fm_u8)((blkB & 0x0004) >> 2);
+
+    WCN_DBG(FM_INF | RDSC, "flag=0x%02x\n", *flag);
+    return 0;
+}
+
+static fm_s32 rds_g0_ps_get(fm_u16 crc, fm_u16 blkD, fm_u8 addr, fm_u8 *buf)
+{
+//    fm_bool valid = fm_false;
+    fm_s32 idx = 0;
+
+    FMR_ASSERT(buf);
+
+    //ps segment addr rang 0~3
+    if (addr > 0x03) {
+        WCN_DBG(FM_ERR | RDSC, "addr invalid(0x%02x)\n", addr);
+        return -FM_EPARA;
+    } else {
+        idx = 2 * addr;
+    }
+
+       buf[idx] = blkD >> 8;
+       buf[idx+1] = blkD & 0xFF;
+       #if 0
+    rds_checksum_check(crc, FM_RDS_GDBK_IND_D, &valid);
+
+    if (valid == fm_true) {
+        buf[idx] = blkD >> 8;
+        buf[idx+1] = blkD & 0xFF;
+    } else {
+        WCN_DBG(FM_ERR | RDSC, "ps crc check err\n");
+        return -FM_ECRC;
+    }
+    #endif
+
+    WCN_DBG(FM_NTC | RDSC, "PS:addr[%02x]:0x%02x 0x%02x\n", addr, buf[idx], buf[idx+1]);
+    return 0;
+}
+
+/*
+ * rds_g0_ps_cmp
+ * this function is the most importent flow for PS parsing
+ * 1.Compare fresh buf with once buf per byte, if eque copy this byte to twice buf, else copy it to once buf
+ * 2.Check wether we got a full segment
+ * If success return 0, else return error code
+*/
+static fm_s32 rds_g0_ps_cmp(fm_u8 addr, fm_u16 cbc, fm_u8 *fresh,
+                            fm_u8 *once, fm_u8 *twice, /*fm_bool *valid,*/fm_u8 *bm)
+{
+       fm_s32 ret = 0,indx;
+       //    fm_s32 i = 0;
+       //fm_s32 j = 0;
+       //    fm_s32 cnt = 0;
+       fm_u8 AF_H, AF_L,PS_Num;
+       //fm_u8 corrBitCnt_BlkB, corrBitCnt_BlkD;
+       static fm_s8 Pre_PS_Num = -1;
+
+       FMR_ASSERT(fresh);
+       FMR_ASSERT(once);
+       FMR_ASSERT(twice);
+//     FMR_ASSERT(valid);
+
+       //j = 2; // PS segment width
+       PS_Num = addr;
+       //corrBitCnt_BlkB = rds_cbc_get(cbc, RDS_BLK_B);
+       //corrBitCnt_BlkD = rds_cbc_get(cbc, RDS_BLK_D);
+
+       AF_H = once[2*PS_Num];
+       AF_L = once[2*PS_Num+1];
+       if((AF_H == fresh[2*PS_Num])&&(AF_L == fresh[2*PS_Num+1]))
+       {
+               twice[2*PS_Num] = once[2*PS_Num];
+               twice[2*PS_Num+1] = once[2*PS_Num+1];
+               *bm |= 1<<PS_Num;
+       }
+       else
+       {
+               if (PS_Num-Pre_PS_Num > 1) 
+               {
+                       for (indx=Pre_PS_Num+1; indx<PS_Num; indx++) 
+                       {
+                               *bm &= ~(1<<indx);
+                               once[2*indx] = 0x00;
+                               once[2*indx+1] = 0x00;
+                               twice[2*indx] = 0x00;
+                               twice[2*indx+1] = 0x00;
+                       }
+               }
+               else if (PS_Num-Pre_PS_Num < 1) 
+               {
+                       for (indx=0; indx<PS_Num; indx++) 
+                       {
+                               *bm &= ~(1<<indx);
+                               once[2*indx] = 0x00;
+                               once[2*indx+1] = 0x00;
+                               twice[2*indx] = 0x00;
+                               twice[2*indx+1] = 0x00;
+                       }
+               }
+               
+               if ((once[2*PS_Num] != 0) || (once[2*PS_Num+1] != 0)) 
+               {
+                       for (indx=PS_Num; indx<4; indx++) 
+                       {
+                               *bm &= ~(1<<indx);
+                       }
+               }
+               //if((corrBitCnt_BlkB == 0) && (corrBitCnt_BlkD == 0)) 
+               if(cbc==0)
+        {
+                       *bm |= 1<<PS_Num;       
+                       once[2*PS_Num]=fresh[2*PS_Num];
+                       once[2*PS_Num+1] = fresh[2*PS_Num+1];
+                       twice[2*PS_Num]=fresh[2*PS_Num];
+                       twice[2*PS_Num+1] = fresh[2*PS_Num+1];
+               } 
+               else 
+               {
+                       once[2*PS_Num]=fresh[2*PS_Num];
+                       once[2*PS_Num+1] = fresh[2*PS_Num+1];
+               }
+       }
+       
+       Pre_PS_Num = PS_Num;
+#if    0
+       if (rds_cbc_get(cbc, RDS_BLK_D) == 0) {
+           once[j*addr] = fresh[j*addr];
+           once[j*addr+1] = fresh[j*addr+1];
+       }
+       if((once[j*addr] == fresh[j*addr])&&(once[j*addr+1] == fresh[j*addr+1]))
+       {
+               twice[j*addr] = once[j*addr];
+               twice[j*addr+1] = once[j*addr+1];
+               *valid = fm_true;
+       }
+       else
+       {
+               once[j*addr] = fresh[j*addr];
+               once[j*addr+1] = fresh[j*addr+1];
+               *valid = fm_false;
+       }
+#endif
+#if    0
+    for (i = 0; i < j; i++) {
+        if (fresh[j*addr+i] == once[j*addr+i]) {
+            twice[j*addr+i] = once[j*addr+i]; //get the same byte 2 times
+            cnt++;
+        } else {
+            once[j*addr+i] = fresh[j*addr+i]; //use new val
+        }
+    }
+
+    //check if we got a valid segment
+    if (cnt == j) {
+        *valid = fm_true;
+    } else {
+        *valid = fm_false;
+    }
+#endif
+    //WCN_DBG(FM_NTC | RDSC, "PS seg=%s\n", *valid == fm_true ? "fm_true" : "fm_false");
+    WCN_DBG(FM_NTC | RDSC, "bitmap=%x\n", *bm);
+    WCN_DBG(FM_NTC | RDSC, "PS[1]=%x %x %x %x %x %x %x %x\n", once[0],once[1],once[2],once[3],once[4],once[5],once[6],once[7]);
+    WCN_DBG(FM_NTC | RDSC, "PS[2]=%x %x %x %x %x %x %x %x\n", twice[0],twice[1],twice[2],twice[3],twice[4],twice[5],twice[6],twice[7]);
+    return ret;
+}
+
+struct rds_bitmap {
+    fm_u16 bm;
+    fm_s32 cnt;
+    fm_s32 max_addr;
+    fm_u16(*bm_get)(struct rds_bitmap *thiz);
+    fm_s32(*bm_cnt_get)(struct rds_bitmap *thiz);
+    fm_s32(*bm_get_pos)(struct rds_bitmap *thiz);
+    fm_s32(*bm_clr)(struct rds_bitmap *thiz);
+    fm_s32(*bm_cmp)(struct rds_bitmap *thiz, struct rds_bitmap *that);
+    fm_s32(*bm_set)(struct rds_bitmap *thiz, fm_u8 addr);
+};
+
+static fm_u16 rds_bm_get(struct rds_bitmap *thiz)
+{
+    return thiz->bm;
+}
+
+static fm_s32 rds_bm_cnt_get(struct rds_bitmap *thiz)
+{
+    return thiz->cnt;
+}
+
+#define FM_RDS_USE_SOLUTION_B
+
+static fm_s32 rds_bm_get_pos(struct rds_bitmap *thiz)
+{
+    fm_s32 i = thiz->max_addr;
+    fm_s32 j;
+
+    j = 0;
+
+    while (!(thiz->bm & (1 << i)) && (i > -1)) {
+        i--;
+    }
+
+#ifdef FM_RDS_USE_SOLUTION_B
+    for (j = i; j >= 0; j--) {
+        if (!(thiz->bm & (1 << j))) {
+            WCN_DBG(FM_NTC | RDSC, "uncomplete msg 0x%04x, delete it\n", thiz->bm);
+            return -1;
+        }
+    }
+#endif
+
+    return i;
+}
+
+static fm_s32 rds_bm_clr(struct rds_bitmap *thiz)
+{
+    thiz->bm = 0x0000;
+    thiz->cnt = 0;
+    return 0;
+}
+
+static fm_s32 rds_bm_cmp(struct rds_bitmap *bitmap1, struct rds_bitmap *bitmap2)
+{
+    return (fm_s32)(bitmap1->bm - bitmap2->bm);
+}
+
+static fm_s32 rds_bm_set(struct rds_bitmap *thiz, fm_u8 addr)
+{
+    struct rds_bitmap bm_old;
+
+    //text segment addr rang
+    if (addr > thiz->max_addr) {
+        WCN_DBG(FM_ERR | RDSC, "addr invalid(0x%02x)\n", addr);
+        return -FM_EPARA;
+    }
+
+    bm_old.bm = thiz->bm;
+    thiz->bm |= (1 << addr); //set bitmap
+
+    if (!rds_bm_cmp(&bm_old, thiz)) {
+        thiz->cnt++;  // multi get a segment
+    } else if (thiz->cnt > 0) {
+        thiz->cnt--;
+    }
+
+    return 0;
+}
+
+
+/*
+ * rds_g2_rt_addr_get
+ * To get rt addr form blockB
+ * If success return 0, else return error code
+*/
+static fm_s32 rds_g2_rt_addr_get(fm_u16 blkB, fm_u8 *addr)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(addr);
+    *addr = (fm_u8)blkB & 0x0F;
+
+    WCN_DBG(FM_INF | RDSC, "addr=0x%02x\n", *addr);
+    return ret;
+}
+
+static fm_s32 rds_g2_txtAB_get(fm_u16 blk, fm_u8 *txtAB, fm_bool *dirty)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(txtAB);
+    FMR_ASSERT(dirty);
+
+       if (*txtAB != ((blk&0x0010) >> 4)) 
+       {
+               *txtAB = (blk & 0x0010) >> 4;
+               *dirty = fm_true; // yes, we got new txtAB code
+               WCN_DBG(FM_INF | RDSC, "changed! txtAB=%d\n", *txtAB);
+    } else {
+        *dirty = fm_false; // txtAB is the same as last one
+    }
+
+    WCN_DBG(FM_INF | RDSC, "txtAB=%d, %s\n", *txtAB, *dirty ? "new" : "old");
+    return ret;
+}
+
+static fm_s32 rds_g2_rt_get(fm_u16 crc, fm_u8 subtype, fm_u16 blkC, fm_u16 blkD, fm_u8 addr, fm_u8 *buf)
+{
+    fm_s32 ret = 0;
+    fm_bool valid = fm_false;
+    fm_s32 idx = 0;
+
+    FMR_ASSERT(buf);
+
+    //text segment addr rang 0~15
+    if (addr > 0x0F) {
+        WCN_DBG(FM_ERR | RDSC, "addr invalid(0x%02x)\n", addr);
+        ret = -FM_EPARA;
+        return ret;
+    }
+
+    switch (subtype) {
+    case RDS_GRP_VER_A:
+        idx = 4 * addr;
+        ret = rds_checksum_check(crc, FM_RDS_GDBK_IND_C | FM_RDS_GDBK_IND_D, &valid);
+
+        if (valid == fm_true) {
+            buf[idx] = blkC >> 8;
+            buf[idx+1] = blkC & 0xFF;
+            buf[idx+2] = blkD >> 8;
+            buf[idx+3] = blkD & 0xFF;
+        } else {
+            WCN_DBG(FM_ERR | RDSC, "rt crc check err\n");
+            ret = -FM_ECRC;
+        }
+
+        break;
+    case RDS_GRP_VER_B:
+        idx = 2 * addr;
+        ret = rds_checksum_check(crc, FM_RDS_GDBK_IND_D, &valid);
+
+        if (valid == fm_true) {
+            buf[idx] = blkD >> 8;
+            buf[idx+1] = blkD & 0xFF;
+        } else {
+            WCN_DBG(FM_ERR | RDSC, "rt crc check err\n");
+            ret = -FM_ECRC;
+        }
+
+        break;
+    default:
+        break;
+    }
+
+    WCN_DBG(FM_NTC | RDSC, "fresh addr[%02x]:0x%02x%02x 0x%02x%02x\n", addr, buf[idx], buf[idx+1], buf[idx+2], buf[idx+3]);
+    return ret;
+}
+
+static fm_s32 rds_g2_rt_get_len(fm_u8 subtype, fm_s32 pos, fm_s32 *len)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(len);
+
+    if (subtype == RDS_GRP_VER_A) {
+        *len = 4 * (pos + 1);
+    } else {
+        *len = 2 * (pos + 1);
+    }
+
+    return ret;
+}
+
+/*
+ * rds_g2_rt_cmp
+ * this function is the most importent flow for RT parsing
+ * 1.Compare fresh buf with once buf per byte, if eque copy this byte to twice buf, else copy it to once buf
+ * 2.Check wether we got a full segment, for typeA if copyed 4bytes to twice buf, for typeB 2bytes copyed to twice buf
+ * 3.Check wether we got the end of RT, if we got 0x0D
+ * 4.If we got the end, then caculate the RT lenth
+ * If success return 0, else return error code
+*/
+static fm_s32 rds_g2_rt_cmp(fm_u8 addr, fm_u16 cbc, fm_u8 subtype, fm_u8 *fresh,
+                            fm_u8 *once, fm_u8 *twice, fm_bool *valid/*, fm_bool *end, fm_s32 *len*/)
+{
+    fm_s32 ret = 0;
+    fm_s32 i = 0;
+    fm_s32 j = 0;
+    fm_s32 cnt = 0;
+
+    FMR_ASSERT(fresh);
+    FMR_ASSERT(once);
+    FMR_ASSERT(twice);
+    FMR_ASSERT(valid);
+//    FMR_ASSERT(end);
+
+    j = (subtype == RDS_GRP_VER_A) ? 4 : 2; // RT segment width
+
+    if (subtype == RDS_GRP_VER_A) {
+        //if (rds_cbc_get(cbc, RDS_BLK_C) == 0) 
+        if(cbc==0)
+        {
+            once[j*addr+0] = fresh[j*addr+0];
+            once[j*addr+1] = fresh[j*addr+1];
+        //}
+
+        //if (rds_cbc_get(cbc, RDS_BLK_D) == 0) 
+       // {
+            once[j*addr+2] = fresh[j*addr+2];
+            once[j*addr+3] = fresh[j*addr+3];
+        }
+    } else if (subtype == RDS_GRP_VER_B) {
+        //if (rds_cbc_get(cbc, RDS_BLK_D) == 0)
+               if(cbc==0)
+        {
+            once[j*addr+0] = fresh[j*addr+0];
+            once[j*addr+1] = fresh[j*addr+1];
+        }
+    }
+
+    for (i = 0; i < j; i++) {
+        if (fresh[j*addr+i] == once[j*addr+i]) {
+            twice[j*addr+i] = once[j*addr+i]; //get the same byte 2 times
+            cnt++;
+                       WCN_DBG(FM_NTC | RDSC, "twice=%d\n", j*addr+i);
+        } else {
+            once[j*addr+i] = fresh[j*addr+i]; //use new val
+                       WCN_DBG(FM_NTC | RDSC, "once=%d\n", j*addr+i);
+        }
+#if 0
+        //if we got 0x0D twice, it means a RT end
+        if (twice[j*addr+i] == 0x0D) {
+            *end = fm_true;
+            *len = j * addr + i + 1; //record the length of RT
+                       WCN_DBG(FM_NTC | RDSC, "get 0D=%d\n", *len);
+        }
+#endif        
+    }
+
+    //check if we got a valid segment 4bytes for typeA, 2bytes for typeB
+    if (cnt == j) {
+        *valid = fm_true;
+    } else {
+        *valid = fm_false;
+    }
+
+    WCN_DBG(FM_INF | RDSC, "RT seg=%s\n", *valid == fm_true ? "fm_true" : "fm_false");
+//    WCN_DBG(FM_INF | RDSC, "RT end=%s\n", *end == fm_true ? "fm_true" : "fm_false");
+//    WCN_DBG(FM_INF | RDSC, "RT len=%d\n", *len);
+    return ret;
+}
+
+/*
+ * rds_g2_rt_check_end
+ * check 0x0D end flag
+ * If we got the end, then caculate the RT lenth
+ * If success return 0, else return error code
+*/
+static fm_s32 rds_g2_rt_check_end(fm_u8 addr, fm_u8 subtype, fm_u8 *twice,fm_bool *end)
+{
+    fm_s32 i = 0;
+    fm_s32 j = 0;
+
+    FMR_ASSERT(twice);
+    FMR_ASSERT(end);
+
+    j = (subtype == RDS_GRP_VER_A) ? 4 : 2; // RT segment width
+       *end = fm_false;
+
+    for (i = 0; i < j; i++) 
+    {
+        //if we got 0x0D twice, it means a RT end
+        if (twice[j*addr+i] == 0x0D) 
+        {
+            *end = fm_true;
+                       WCN_DBG(FM_NTC | RDSC, "get 0x0D\n");
+                       break;
+        }
+    }
+
+    return 0;
+}
+
+static fm_s32 rds_retrieve_g0_af(fm_u16 *block_data, fm_u8 SubType, rds_t *pstRDSData)
+{
+    static fm_s16 preAF_Num = 0;
+    fm_u8 indx, indx2, AF_H, AF_L, num;
+    fm_s32 ret = 0;
+    fm_bool valid = fm_false;
+    fm_bool dirty = fm_false;
+    fm_u16 *event = &pstRDSData->event_status;
+    fm_u32 *flag = &pstRDSData->RDSFlag.flag_status;
+
+//    ret = rds_checksum_check(block_data[4], FM_RDS_GDBK_IND_D, &valid);
+
+//    if (valid == fm_false) {
+//        WCN_DBG(FM_WAR | RDSC, "Group0 BlockD crc err\n");
+//        return -FM_ECRC;
+//    }
+
+    ret = rds_g0_ta_get(block_data[1], &pstRDSData->RDSFlag.TA, &dirty);
+
+    if (ret) {
+        WCN_DBG(FM_WAR | RDSC, "get ta failed[ret=%d]\n", ret);
+    } else if (dirty == fm_true) {
+        ret = rds_event_set(event, RDS_EVENT_FLAGS); // yes, we got new TA code
+        ret = rds_flag_set(flag, RDS_FLAG_IS_TA);
+    }
+
+    ret = rds_g0_music_get(block_data[1], &pstRDSData->RDSFlag.Music, &dirty);
+
+    if (ret) {
+        WCN_DBG(FM_WAR | RDSC, "get music failed[ret=%d]\n", ret);
+    } else if (dirty == fm_true) {
+        ret = rds_event_set(event, RDS_EVENT_FLAGS); // yes, we got new MUSIC code
+        ret = rds_flag_set(flag, RDS_FLAG_IS_MUSIC);
+    }
+
+    if ((pstRDSData->Switch_TP) && (pstRDSData->RDSFlag.TP) && !(pstRDSData->RDSFlag.TA)) {
+        ret = rds_event_set(event, RDS_EVENT_TAON_OFF);
+    }
+
+    if (!SubType) {
+        //Type A
+        ret = rds_checksum_check(block_data[4], FM_RDS_GDBK_IND_C, &valid);
+
+        if (valid == fm_false) {
+            WCN_DBG(FM_WAR | RDSC, "Group0 BlockC crc err\n");
+            return -FM_ECRC;
+        } else {
+            AF_H = (block_data[2] & 0xFF00) >> 8;
+            AF_L = block_data[2] & 0x00FF;
+
+            if ((AF_H > 224) && (AF_H < 250)) {
+                //Followed AF Number, see RDS spec Table 11, valid(224-249)
+                WCN_DBG(FM_NTC | RDSC, "RetrieveGroup0 AF_H:%d, AF_L:%d\n", AF_H, AF_L);
+                preAF_Num = AF_H - 224; //AF Number
+
+                if (preAF_Num != pstRDSData->AF_Data.AF_Num) {
+                    pstRDSData->AF_Data.AF_Num = preAF_Num;
+                                       pstRDSData->AF_Data.isAFNum_Get = 0;
+                } else {
+                    //Get the same AFNum two times
+                    pstRDSData->AF_Data.isAFNum_Get = 1;
+                }
+
+                if ((AF_L < 205) && (AF_L > 0)) {
+                    //See RDS Spec table 10, valid VHF
+                    pstRDSData->AF_Data.AF[0][0] = AF_L + 875; //convert to 100KHz
+#ifdef MTK_FM_50KHZ_SUPPORT
+                    pstRDSData->AF_Data.AF[0][0] *= 10;
+#endif
+                    WCN_DBG(FM_NTC | RDSC, "RetrieveGroup0 AF[0][0]:%d\n", pstRDSData->AF_Data.AF[0][0]);
+
+                    if ((pstRDSData->AF_Data.AF[0][0]) != (pstRDSData->AF_Data.AF[1][0])) {
+                        pstRDSData->AF_Data.AF[1][0] = pstRDSData->AF_Data.AF[0][0];
+                    } else {
+                        if (pstRDSData->AF_Data.AF[1][0] !=  rds_get_freq())
+                            pstRDSData->AF_Data.isMethod_A = 1;
+                        else
+                            pstRDSData->AF_Data.isMethod_A = 0;
+                    }
+
+                    WCN_DBG(FM_NTC | RDSC, "RetrieveGroup0 isAFNum_Get:%d, isMethod_A:%d\n", pstRDSData->AF_Data.isAFNum_Get, pstRDSData->AF_Data.isMethod_A);
+
+                    //only one AF handle
+                    if ((pstRDSData->AF_Data.isAFNum_Get) && (pstRDSData->AF_Data.AF_Num == 1)) {
+                        pstRDSData->AF_Data.Addr_Cnt = 0xFF;
+                        pstRDSData->event_status |= RDS_EVENT_AF_LIST;
+                        WCN_DBG(FM_NTC | RDSC, "RetrieveGroup0 RDS_EVENT_AF_LIST update\n");
+                    }
+                }
+            }
+                       else if ((pstRDSData->AF_Data.isAFNum_Get) && (pstRDSData->AF_Data.Addr_Cnt != 0xFF)) {
+                //AF Num correct
+                num = pstRDSData->AF_Data.AF_Num;
+                num = num >> 1;
+                WCN_DBG(FM_NTC | RDSC, "RetrieveGroup0 +num:%d\n", num);
+
+                //Put AF freq fm_s32o buffer and check if AF freq is repeat again
+                for (indx = 1; indx < (num + 1); indx++) {
+                    if ((AF_H == (pstRDSData->AF_Data.AF[0][2*indx-1])) && (AF_L == (pstRDSData->AF_Data.AF[0][2*indx]))) {
+                        WCN_DBG(FM_ERR | RDSC, "RetrieveGroup0 AF same as indx:%d\n", indx);
+                        break;
+                    } else if (!(pstRDSData->AF_Data.AF[0][2*indx-1])) {
+                        //null buffer
+                        pstRDSData->AF_Data.AF[0][2*indx-1] = AF_H + 875; //convert to 100KHz
+                        pstRDSData->AF_Data.AF[0][2*indx] = AF_L + 875;
+                        
+#ifdef MTK_FM_50KHZ_SUPPORT
+                        pstRDSData->AF_Data.AF[0][2*indx-1] *= 10;
+                        pstRDSData->AF_Data.AF[0][2*indx] *= 10;
+#endif
+                        WCN_DBG(FM_NTC | RDSC, "RetrieveGroup0 AF[0][%d]:%d, AF[0][%d]:%d\n",
+                                2*indx - 1, pstRDSData->AF_Data.AF[0][2*indx-1], 2*indx, pstRDSData->AF_Data.AF[0][2*indx]);
+                        break;
+                    }
+                }
+
+                num = pstRDSData->AF_Data.AF_Num;
+                WCN_DBG(FM_NTC | RDSC, "RetrieveGroup0 ++num:%d\n", num);
+
+                if (num > 0) {
+                    if ((pstRDSData->AF_Data.AF[0][num-1]) != 0) {
+                        num = num >> 1;
+                        WCN_DBG(FM_NTC | RDSC, "RetrieveGroup0 +++num:%d\n", num);
+
+                        //arrange frequency from low to high:start
+                        for (indx = 1; indx < num; indx++) {
+                            for (indx2 = indx + 1; indx2 < (num + 1); indx2++) {
+                                AF_H = pstRDSData->AF_Data.AF[0][2*indx-1];
+                                AF_L = pstRDSData->AF_Data.AF[0][2*indx];
+
+                                if (AF_H > (pstRDSData->AF_Data.AF[0][2*indx2-1])) {
+                                    pstRDSData->AF_Data.AF[0][2*indx-1] = pstRDSData->AF_Data.AF[0][2*indx2-1];
+                                    pstRDSData->AF_Data.AF[0][2*indx] = pstRDSData->AF_Data.AF[0][2*indx2];
+                                    pstRDSData->AF_Data.AF[0][2*indx2-1] = AF_H;
+                                    pstRDSData->AF_Data.AF[0][2*indx2] = AF_L;
+                                } else if (AF_H == (pstRDSData->AF_Data.AF[0][2*indx2-1])) {
+                                    if (AF_L > (pstRDSData->AF_Data.AF[0][2*indx2])) {
+                                        pstRDSData->AF_Data.AF[0][2*indx-1] = pstRDSData->AF_Data.AF[0][2*indx2-1];
+                                        pstRDSData->AF_Data.AF[0][2*indx] = pstRDSData->AF_Data.AF[0][2*indx2];
+                                        pstRDSData->AF_Data.AF[0][2*indx2-1] = AF_H;
+                                        pstRDSData->AF_Data.AF[0][2*indx2] = AF_L;
+                                    }
+                                }
+                            }
+                        }
+
+                        //arrange frequency from low to high:end
+                        //compare AF buff0 and buff1 data:start
+                        num = pstRDSData->AF_Data.AF_Num;
+                        indx2 = 0;
+
+                        for (indx = 0; indx < num; indx++) {
+                            if ((pstRDSData->AF_Data.AF[1][indx]) == (pstRDSData->AF_Data.AF[0][indx])) {
+                                if (pstRDSData->AF_Data.AF[1][indx] != 0)
+                                    indx2++;
+                            } else
+                                pstRDSData->AF_Data.AF[1][indx] = pstRDSData->AF_Data.AF[0][indx];
+                        }
+
+                        WCN_DBG(FM_NTC | RDSC, "RetrieveGroup0 indx2:%d, num:%d\n", indx2, num);
+
+                        //compare AF buff0 and buff1 data:end
+                        if (indx2 == num) {
+                            pstRDSData->AF_Data.Addr_Cnt = 0xFF;
+                            pstRDSData->event_status |= RDS_EVENT_AF_LIST;
+                            WCN_DBG(FM_NTC | RDSC, "RetrieveGroup0 AF_Num:%d\n", pstRDSData->AF_Data.AF_Num);
+
+                            for (indx = 0; indx < num; indx++) {
+                                if ((pstRDSData->AF_Data.AF[1][indx]) == 0) {
+                                    pstRDSData->AF_Data.Addr_Cnt = 0x0F;
+                                    pstRDSData->event_status &= (~RDS_EVENT_AF_LIST);
+                                }
+                            }
+                        } else
+                            pstRDSData->AF_Data.Addr_Cnt = 0x0F;
+                    }
+                }
+            }
+        }
+    }
+
+    return ret;
+}
+
+static fm_s32 rds_retrieve_g0_di(fm_u16 *block_data, fm_u8 SubType, rds_t *pstRDSData)
+{
+    fm_u8 DI_Code, DI_Flag;
+    fm_s32 ret = 0;
+//    fm_bool valid = fm_false;
+
+    fm_u16 *event = &pstRDSData->event_status;
+    fm_u32 *flag = &pstRDSData->RDSFlag.flag_status;
+
+    //parsing Program service name segment (in BlockD)
+//    ret = rds_checksum_check(block_data[4], FM_RDS_GDBK_IND_D, &valid);
+
+//    if (valid == fm_false) {
+//        WCN_DBG(FM_WAR | RDSC, "Group0 BlockD crc err\n");
+//        return -FM_ECRC;
+//    }
+
+    rds_g0_ps_addr_get(block_data[1], &DI_Code);
+    rds_g0_di_flag_get(block_data[1], &DI_Flag);
+
+    switch (DI_Code) {
+    case 3:
+
+        if (pstRDSData->RDSFlag.Stereo != DI_Flag) {
+            pstRDSData->RDSFlag.Stereo = DI_Flag;
+            ret = rds_event_set(event, RDS_EVENT_FLAGS);
+            ret = rds_flag_set(flag, RDS_FLAG_IS_STEREO);
+        }
+
+        break;
+    case 2:
+
+        if (pstRDSData->RDSFlag.Artificial_Head != DI_Flag) {
+            pstRDSData->RDSFlag.Artificial_Head = DI_Flag;
+            ret = rds_event_set(event, RDS_EVENT_FLAGS);
+            ret = rds_flag_set(flag, RDS_FLAG_IS_ARTIFICIAL_HEAD);
+        }
+
+        break;
+    case 1:
+
+        if (pstRDSData->RDSFlag.Compressed != DI_Flag) {
+            pstRDSData->RDSFlag.Compressed = DI_Flag;
+            ret = rds_event_set(event, RDS_EVENT_FLAGS);
+            ret = rds_flag_set(flag, RDS_FLAG_IS_COMPRESSED);
+        }
+
+        break;
+    case 0:
+
+        if (pstRDSData->RDSFlag.Dynamic_PTY != DI_Flag) {
+            pstRDSData->RDSFlag.Dynamic_PTY = DI_Flag;
+            ret = rds_event_set(event, RDS_EVENT_FLAGS);
+            ret = rds_flag_set(flag, RDS_FLAG_IS_DYNAMIC_PTY);
+        }
+
+        break;
+    default:
+        break;
+    }
+
+    return ret;
+}
+
+static fm_s32 rds_retrieve_g0_ps(fm_u16 *block_data, fm_u8 SubType, rds_t *pstRDSData)
+{
+    fm_u8 ps_addr;
+    fm_s32 ret = 0,i,num;
+    fm_bool valid = fm_false;
+//    fm_s32 pos = 0;
+    static struct fm_state_machine ps_sm = {
+        .state = RDS_PS_START,
+        .state_get = fm_state_get,
+        .state_set = fm_state_set,
+    };
+#if 0     
+    static struct rds_bitmap ps_bm = {
+        .bm = 0,
+        .cnt = 0,
+        .max_addr = 0x03,
+        .bm_get = rds_bm_get,
+        .bm_cnt_get = rds_bm_cnt_get,
+        .bm_set = rds_bm_set,
+        .bm_get_pos = rds_bm_get_pos,
+        .bm_clr = rds_bm_clr,
+        .bm_cmp = rds_bm_cmp,
+    };
+#endif
+    fm_u16 *event = &pstRDSData->event_status;
+
+    //parsing Program service name segment (in BlockD)
+    ret = rds_checksum_check(block_data[4], FM_RDS_GDBK_IND_D, &valid);
+
+    if (valid == fm_false) {
+        WCN_DBG(FM_WAR | RDSC, "Group0 BlockD crc err\n");
+        return -FM_ECRC;
+    }
+
+    rds_g0_ps_addr_get(block_data[1], &ps_addr);
+
+    //PS parsing state machine run
+    while (1) {
+        switch (STATE_GET(&ps_sm)) {
+        case RDS_PS_START:
+
+            if (rds_g0_ps_get(block_data[4], block_data[3], ps_addr, pstRDSData->PS_Data.PS[0])) {
+                STATE_SET(&ps_sm, RDS_PS_FINISH); //if CRC error, we should not do parsing
+                break;
+            }
+
+            rds_g0_ps_cmp(ps_addr, block_data[5], pstRDSData->PS_Data.PS[0],
+                          pstRDSData->PS_Data.PS[1], pstRDSData->PS_Data.PS[2], /*&valid,*/&pstRDSData->PS_Data.Addr_Cnt);
+
+           // if (valid == fm_true) {
+           //     ps_bm.bm_set(&ps_bm, ps_addr);
+           // }
+
+            STATE_SET(&ps_sm, RDS_PS_DECISION);
+            break;
+        case RDS_PS_DECISION:
+
+            if (pstRDSData->PS_Data.Addr_Cnt == 0x000F) //get max  8 chars
+               //ps shouldn't check bm_cnt
+               //     || (ps_bm.bm_cnt_get(&ps_bm) > RDS_RT_MULTI_REV_TH)) { //repeate many times, but no end char get
+            {
+               //pos = ps_bm.bm_get_pos(&ps_bm);
+                STATE_SET(&ps_sm, RDS_PS_GETLEN);
+            } 
+                       else 
+                       {
+                STATE_SET(&ps_sm, RDS_PS_FINISH);
+            }
+
+            break;
+        case RDS_PS_GETLEN:
+            
+            //if (pos == ps_bm.max_addr) 
+                       {
+                               num=0;
+                               WCN_DBG(FM_NTC | RDSC, "PS[3]=%x %x %x %x %x %x %x %x\n", 
+                                                                               pstRDSData->PS_Data.PS[3][0],
+                                                                               pstRDSData->PS_Data.PS[3][1],
+                                                                               pstRDSData->PS_Data.PS[3][2],
+                                                                               pstRDSData->PS_Data.PS[3][3],
+                                                                               pstRDSData->PS_Data.PS[3][4],
+                                                                               pstRDSData->PS_Data.PS[3][5],
+                                                                               pstRDSData->PS_Data.PS[3][6],
+                                                                               pstRDSData->PS_Data.PS[3][7]);
+                               for(i=0;i<8;i++)//compare with last PS.
+                               {
+                                       if(pstRDSData->PS_Data.PS[3][i]==pstRDSData->PS_Data.PS[2][i])
+                                       {
+                                               num++;
+                                       }
+                               }
+                               if(num != 8)
+                               {
+                                       num=0;
+                                       for(i=0;i<8;i++)
+                                       {
+                                               if((pstRDSData->PS_Data.PS[2][i]==0x20)||(pstRDSData->PS_Data.PS[2][i]==0x0))
+                                               {
+                                                       num++;
+                                               }
+                                       }
+                                       if(num != 8)
+                                       {
+                                               fm_memcpy(pstRDSData->PS_Data.PS[3], pstRDSData->PS_Data.PS[2], 8);
+                                               rds_event_set(event, RDS_EVENT_PROGRAMNAME); //yes we got a new PS
+                                               WCN_DBG(FM_NTC | RDSC, "Yes, get an PS!\n");
+                                       }
+                               }
+                               else
+                               {
+                                       pstRDSData->PS_Data.Addr_Cnt=0;
+                                       //clear buf
+                                       fm_memset(pstRDSData->PS_Data.PS[0], 0x20, 8);
+                                       fm_memset(pstRDSData->PS_Data.PS[1], 0x20, 8);
+                                       fm_memset(pstRDSData->PS_Data.PS[2], 0x20, 8);
+                               }
+            }
+#if 0
+            ps_bm.bm_clr(&ps_bm);
+            //clear buf
+            fm_memset(pstRDSData->PS_Data.PS[0], 0x20, 8);
+            fm_memset(pstRDSData->PS_Data.PS[1], 0x20, 8);
+            fm_memset(pstRDSData->PS_Data.PS[2], 0x20, 8);
+#endif            
+            STATE_SET(&ps_sm, RDS_PS_FINISH);
+            break;
+        case RDS_PS_FINISH:
+            STATE_SET(&ps_sm, RDS_PS_START);
+            goto out;
+            break;
+        default:
+            break;
+        }
+    }
+
+out:
+    return ret;
+}
+
+static fm_s32 rds_retrieve_g0(fm_u16 *block_data, fm_u8 SubType, rds_t *pstRDSData)
+{
+    fm_s32 ret = 0;
+
+    ret = rds_retrieve_g0_af(block_data, SubType, pstRDSData);
+
+    if (ret) {
+        return ret;
+    }
+
+    ret = rds_retrieve_g0_di(block_data, SubType, pstRDSData);
+
+    if (ret) {
+        return ret;
+    }
+
+    ret = rds_retrieve_g0_ps(block_data, SubType, pstRDSData);
+
+    if (ret) {
+        return ret;
+    }
+
+    return ret;
+}
+
+static fm_s32 rds_retrieve_g1(fm_u16 *block_data, fm_u8 SubType, rds_t *pstRDSData)
+{
+    fm_u8 variant_code = (block_data[2] & 0x7000) >> 12;
+    fm_s32 ret = 0;
+
+    if (variant_code == 0) {
+        pstRDSData->Extend_Country_Code = (fm_u8)block_data[2] & 0xFF;
+        WCN_DBG(FM_DBG | RDSC, "Extend_Country_Code:%d\n", pstRDSData->Extend_Country_Code);
+    } else if (variant_code == 3) {
+        pstRDSData->Language_Code = block_data[2] & 0xFFF;
+        WCN_DBG(FM_DBG | RDSC, "Language_Code:%d\n", pstRDSData->Language_Code);
+    }
+
+    pstRDSData->Radio_Page_Code = block_data[1] & 0x001F;
+    pstRDSData->Program_Item_Number_Code = block_data[3];
+
+    return ret;
+}
+
+static fm_s32 rds_retrieve_g2(fm_u16 *source, fm_u8 subtype, rds_t *target)
+{
+    fm_s32 ret = 0;
+    fm_u16 crc, cbc;
+    fm_u16 blkA, blkB, blkC, blkD;
+    fm_u8 *fresh, *once, *twice, *display;
+    fm_u16 *event;
+    fm_u32 *flag;
+    static struct fm_state_machine rt_sm = {
+        .state = RDS_RT_START,
+        .state_get = fm_state_get,
+        .state_set = fm_state_set,
+    };
+    static struct rds_bitmap rt_bm = {
+        .bm = 0,
+        .cnt = 0,
+        .max_addr = 0xF,
+        .bm_get = rds_bm_get,
+        .bm_cnt_get = rds_bm_cnt_get,
+        .bm_set = rds_bm_set,
+        .bm_get_pos = rds_bm_get_pos,
+        .bm_clr = rds_bm_clr,
+        .bm_cmp = rds_bm_cmp,
+    };
+    fm_u8 rt_addr = 0;
+    fm_bool txtAB_change = fm_false;  //text AB flag 0 --> 1 or 1-->0 meas new RT incoming
+    fm_bool txt_end = fm_false;       //0x0D means text end
+    fm_bool seg_ok = 0;
+    fm_s32 pos = 0;
+    fm_s32 rt_len = 0,indx=0,invalid_cnt=0;
+    fm_s32 bufsize = 0;
+
+    FMR_ASSERT(source);
+    FMR_ASSERT(target);
+    //source
+    blkA = source[0];
+    blkB = source[1];
+    blkC = source[2];
+    blkD = source[3];
+    crc = source[4];
+    cbc = source[5];
+    //target
+    fresh = target->RT_Data.TextData[0];
+    once = target->RT_Data.TextData[1];
+    twice = target->RT_Data.TextData[2];
+    display = target->RT_Data.TextData[3];
+    event = &target->event_status;
+    flag = &target->RDSFlag.flag_status;
+    bufsize = sizeof(target->RT_Data.TextData[0]);
+       rt_bm.bm = target->RT_Data.Addr_Cnt;
+
+    //get basic info: addr, txtAB
+    if (rds_g2_rt_addr_get(blkB, &rt_addr))
+        return ret;
+
+    if (rds_g2_txtAB_get(blkB, &target->RDSFlag.Text_AB, &txtAB_change))
+        return ret;
+       if(txtAB_change == fm_true)
+       {
+               //clear buf
+               fm_memset(fresh, 0x20, bufsize);
+               fm_memset(once, 0x20, bufsize);
+               fm_memset(twice, 0x20, bufsize);
+               rt_bm.bm_clr(&rt_bm);
+       }
+    //RT parsing state machine run
+    while (1) {
+        switch (STATE_GET(&rt_sm)) {
+        case RDS_RT_START:
+               {
+#if 0
+            if (txtAB_change == fm_true)
+            {
+                STATE_SET(&rt_sm, RDS_RT_DECISION);
+            } 
+            else 
+#endif
+            {
+                if (rds_g2_rt_get(crc, subtype, blkC, blkD, rt_addr, fresh) == 0) 
+                {
+                    //STATE_SET(&rt_sm, RDS_RT_FINISH); //if CRC error, we should not do parsing
+                    //break;
+                                       rds_g2_rt_cmp(rt_addr, cbc, subtype, fresh, once, twice,
+                                                                 &seg_ok/*, &txt_end, &rt_len*/);
+                                       
+                                       if (seg_ok == fm_true) 
+                                       {
+                                               rt_bm.bm_set(&rt_bm, rt_addr);
+                                       }
+                                       else//clear bitmap of rt_addr
+                                       {
+                                               rt_bm.bm &= ~(1<<rt_addr);
+                                       }
+                }
+                               WCN_DBG(FM_NTC | RDSC, "bitmap=0x%04x, bmcnt=%d\n", rt_bm.bm, rt_bm.cnt);
+                               rds_g2_rt_check_end(rt_addr,subtype,twice,&txt_end);
+
+                STATE_SET(&rt_sm, RDS_RT_DECISION);
+            }
+                       break;
+               }
+        case RDS_RT_DECISION:
+               {
+                       if ((txt_end == fm_true)
+                               || (rt_bm.bm_get(&rt_bm) == 0xFFFF) //get max  64 chars
+                               || (rt_bm.bm_cnt_get(&rt_bm) > RDS_RT_MULTI_REV_TH))//repeate many times, but no end char get
+            { 
+                pos = rt_bm.bm_get_pos(&rt_bm);
+                rds_g2_rt_get_len(subtype, pos, &rt_len);
+                STATE_SET(&rt_sm, RDS_RT_GETLEN);
+            } 
+            else 
+            {
+                STATE_SET(&rt_sm, RDS_RT_FINISH);
+            }
+
+            break;
+               }
+        case RDS_RT_GETLEN:
+            
+            if (rt_len > 0 /*&& ((txt_end == fm_true) || (rt_bm.bm_get(&rt_bm) == 0xFFFF))*/) 
+            {
+                               for(indx=0; indx<rt_len; indx++)
+                               {
+                                       if(twice[indx] == 0x20)
+                                               invalid_cnt++;
+                               }       
+                               if(invalid_cnt != rt_len)
+                               {
+                                       if(memcmp(display,twice,bufsize)!=0)
+                                       {
+                                               fm_memcpy(display, twice, bufsize);
+                                               target->RT_Data.TextLength = rt_len;
+                               rds_event_set(event, RDS_EVENT_LAST_RADIOTEXT); //yes we got a new RT
+                               WCN_DBG(FM_NTC | RDSC, "Yes, get an RT! [len=%d]\n", rt_len);
+                                       }
+                                       rt_bm.bm_clr(&rt_bm);
+                                       //clear buf
+                                       fm_memset(fresh, 0x20, bufsize);
+                                       fm_memset(once, 0x20, bufsize);
+                                       fm_memset(twice, 0x20, bufsize);
+                }
+                else
+                       WCN_DBG(FM_NTC | RDSC, "Get 0x20 RT %d\n", invalid_cnt);
+            }
+
+#if 0
+            if (txtAB_change == fm_true) {
+                txtAB_change = fm_false;
+                //we need get new RT after show the old RT to the display
+                STATE_SET(&rt_sm, RDS_RT_START);
+            } 
+            else 
+#endif
+            {
+                STATE_SET(&rt_sm, RDS_RT_FINISH);
+            }
+            break;
+        case RDS_RT_FINISH:
+            STATE_SET(&rt_sm, RDS_RT_START);
+            goto out;
+            break;
+        default:
+            break;
+        }
+    }
+
+out:
+       target->RT_Data.Addr_Cnt = rt_bm.bm;
+    return ret;
+}
+
+static fm_s32 rds_retrieve_g4(fm_u16 *block_data, fm_u8 SubType, rds_t *pstRDSData)
+{
+    fm_u16 year, month, k = 0, D2, minute;
+    fm_u32 MJD, D1;
+    fm_s32 ret = 0;
+    WCN_DBG(FM_DBG | RDSC, "RetrieveGroup4 %d\n", SubType);
+
+    if (!SubType) {
+        //Type A
+        if ((block_data[4]&FM_RDS_GDBK_IND_C) && (block_data[4]&FM_RDS_GDBK_IND_D)) {
+            MJD = (fm_u32)(((block_data[1] & 0x0003) << 15) + ((block_data[2] & 0xFFFE) >> 1));
+            year = (MJD * 100 - 1507820) / 36525;
+            month = (MJD * 10000 - 149561000 - 3652500 * year) / 306001;
+
+            if ((month == 14) || (month == 15))
+                k = 1;
+
+            D1 = (fm_u32)((36525 * year) / 100);
+            D2 = (fm_u16)((306001 * month) / 10000);
+            pstRDSData->CT.Year = 1900 + year + k;
+            pstRDSData->CT.Month = month - 1 - k * 12;
+            pstRDSData->CT.Day = (fm_u16)(MJD - 14956 - D1 - D2);
+            pstRDSData->CT.Hour = ((block_data[2] & 0x0001) << 4) + ((block_data[3] & 0xF000) >> 12);
+            minute = (block_data[3] & 0x0FC0) >> 6;
+
+            if (block_data[3]&0x0020) {
+                pstRDSData->CT.Local_Time_offset_signbit = 1; //0=+, 1=-
+            }
+
+            pstRDSData->CT.Local_Time_offset_half_hour = block_data[3] & 0x001F;
+
+            if (pstRDSData->CT.Minute != minute) {
+                pstRDSData->CT.Minute = (block_data[3] & 0x0FC0) >> 6;
+                pstRDSData->event_status |= RDS_EVENT_UTCDATETIME;
+            }
+        }
+    }
+
+    return ret;
+}
+
+static fm_s32 rds_retrieve_g14(fm_u16 *block_data, fm_u8 SubType, rds_t *pstRDSData)
+{
+    static fm_s16 preAFON_Num = 0;
+    fm_u8 TP_ON, TA_ON, PI_ON, PS_Num, AF_H, AF_L, indx, indx2, num;
+    fm_s32 ret = 0;
+    WCN_DBG(FM_DBG | RDSC, "RetrieveGroup14 %d\n", SubType);
+    //SubType = (*(block_data+1)&0x0800)>>11;
+    PI_ON = block_data[3];
+    TP_ON = block_data[1] & 0x0010;
+
+    if ((!SubType) && (block_data[4]&FM_RDS_GDBK_IND_C)) {
+        //Type A
+        PS_Num = block_data[1] & 0x000F;
+
+        if (PS_Num < 4) {
+            for (indx = 0; indx < 2; indx++) {
+                pstRDSData->PS_ON[2*PS_Num] = block_data[2] >> 8;
+                pstRDSData->PS_ON[2*PS_Num+1] = block_data[2] & 0xFF;
+            }
+        } else if (PS_Num == 4) {
+            AF_H = (block_data[2] & 0xFF00) >> 8;
+            AF_L = block_data[2] & 0x00FF;
+
+            if ((AF_H > 224) && (AF_H < 250)) {
+                //Followed AF Number
+                pstRDSData->AFON_Data.isAFNum_Get = 0;
+                preAFON_Num = AF_H - 224;
+
+                if (pstRDSData->AFON_Data.AF_Num != preAFON_Num) {
+                    pstRDSData->AFON_Data.AF_Num = preAFON_Num;
+                } else
+                    pstRDSData->AFON_Data.isAFNum_Get = 1;
+
+                if (AF_L < 205) {
+                    pstRDSData->AFON_Data.AF[0][0] = AF_L + 875;
+
+                    if ((pstRDSData->AFON_Data.AF[0][0]) != (pstRDSData->AFON_Data.AF[1][0])) {
+                        pstRDSData->AFON_Data.AF[1][0] = pstRDSData->AFON_Data.AF[0][0];
+                    } else {
+                        pstRDSData->AFON_Data.isMethod_A = 1;
+                    }
+                }
+            }
+                       else if ((pstRDSData->AFON_Data.isAFNum_Get) && ((pstRDSData->AFON_Data.Addr_Cnt) != 0xFF)) {
+                //AF Num correct
+                num = pstRDSData->AFON_Data.AF_Num;
+                num = num >> 1;
+
+                //Put AF freq fm_s32o buffer and check if AF freq is repeat again
+                for (indx = 1; indx < (num + 1); indx++) {
+                    if ((AF_H == (pstRDSData->AFON_Data.AF[0][2*indx-1])) && (AF_L == (pstRDSData->AFON_Data.AF[0][2*indx]))) {
+                        WCN_DBG(FM_NTC | RDSC, "RetrieveGroup14 AFON same as indx:%d\n", indx);
+                        break;
+                    } else if (!(pstRDSData->AFON_Data.AF[0][2*indx-1])) {
+                        //null buffer
+                        pstRDSData->AFON_Data.AF[0][2*indx-1] = AF_H + 875;
+                        pstRDSData->AFON_Data.AF[0][2*indx] = AF_L + 875;
+                        break;
+                    }
+                }
+
+                num = pstRDSData->AFON_Data.AF_Num;
+
+                if (num > 0) {
+                    if ((pstRDSData->AFON_Data.AF[0][num-1]) != 0) {
+                        num = num >> 1;
+
+                        //arrange frequency from low to high:start
+                        for (indx = 1; indx < num; indx++) {
+                            for (indx2 = indx + 1; indx2 < (num + 1); indx2++) {
+                                AF_H = pstRDSData->AFON_Data.AF[0][2*indx-1];
+                                AF_L = pstRDSData->AFON_Data.AF[0][2*indx];
+
+                                if (AF_H > (pstRDSData->AFON_Data.AF[0][2*indx2-1])) {
+                                    pstRDSData->AFON_Data.AF[0][2*indx-1] = pstRDSData->AFON_Data.AF[0][2*indx2-1];
+                                    pstRDSData->AFON_Data.AF[0][2*indx] = pstRDSData->AFON_Data.AF[0][2*indx2];
+                                    pstRDSData->AFON_Data.AF[0][2*indx2-1] = AF_H;
+                                    pstRDSData->AFON_Data.AF[0][2*indx2] = AF_L;
+                                } else if (AF_H == (pstRDSData->AFON_Data.AF[0][2*indx2-1])) {
+                                    if (AF_L > (pstRDSData->AFON_Data.AF[0][2*indx2])) {
+                                        pstRDSData->AFON_Data.AF[0][2*indx-1] = pstRDSData->AFON_Data.AF[0][2*indx2-1];
+                                        pstRDSData->AFON_Data.AF[0][2*indx] = pstRDSData->AFON_Data.AF[0][2*indx2];
+                                        pstRDSData->AFON_Data.AF[0][2*indx2-1] = AF_H;
+                                        pstRDSData->AFON_Data.AF[0][2*indx2] = AF_L;
+                                    }
+                                }
+                            }
+                        }
+
+                        //arrange frequency from low to high:end
+                        //compare AF buff0 and buff1 data:start
+                        num = pstRDSData->AFON_Data.AF_Num;
+                        indx2 = 0;
+
+                        for (indx = 0; indx < num; indx++) {
+                            if ((pstRDSData->AFON_Data.AF[1][indx]) == (pstRDSData->AFON_Data.AF[0][indx])) {
+                                if (pstRDSData->AFON_Data.AF[1][indx] != 0)
+                                    indx2++;
+                            } else
+                                pstRDSData->AFON_Data.AF[1][indx] = pstRDSData->AFON_Data.AF[0][indx];
+                        }
+
+                        //compare AF buff0 and buff1 data:end
+                        if (indx2 == num) {
+                            pstRDSData->AFON_Data.Addr_Cnt = 0xFF;
+                            pstRDSData->event_status |= RDS_EVENT_AFON_LIST;
+
+                            for (indx = 0; indx < num; indx++) {
+                                if ((pstRDSData->AFON_Data.AF[1][indx]) == 0) {
+                                    pstRDSData->AFON_Data.Addr_Cnt = 0x0F;
+                                    pstRDSData->event_status &= (~RDS_EVENT_AFON_LIST);
+                                }
+                            }
+                        } else
+                            pstRDSData->AFON_Data.Addr_Cnt = 0x0F;
+                    }
+                }
+            }
+        }
+    } else {
+        //Type B
+        TA_ON = block_data[1] & 0x0008;
+        WCN_DBG(FM_DBG | RDSC, "TA g14 typeB pstRDSData->RDSFlag.TP=%d pstRDSData->RDSFlag.TA=%d TP_ON=%d TA_ON=%d\n", pstRDSData->RDSFlag.TP, pstRDSData->RDSFlag.TA, TP_ON, TA_ON);
+
+        if ((!pstRDSData->RDSFlag.TP) && (pstRDSData->RDSFlag.TA) && TP_ON && TA_ON) {
+            fm_s32 TA_num = 0;
+
+            for (num = 0; num < 25; num++) {
+                if (pstRDSData->AFON_Data.AF[1][num] != 0) {
+                    TA_num++;
+                } else {
+                    break;
+                }
+            }
+
+            WCN_DBG(FM_NTC | RDSC, "TA set RDS_EVENT_TAON");
+
+            if (TA_num == pstRDSData->AFON_Data.AF_Num) {
+                pstRDSData->event_status |= RDS_EVENT_TAON;
+            }
+        }
+    }
+
+    return ret;
+}
+
+/*
+ *  rds_parser
+ *  Block0:    PI code(16bits)
+ *  Block1:    Group type(4bits), B0=version code(1bit), TP=traffic program code(1bit),
+ *  PTY=program type code(5bits), other(5bits)
+ *  Block2:    16bits
+ *  Block3:    16bits
+ *  @rds_dst - target buffer that record RDS parsing result
+ *  @rds_raw - rds raw data
+ *  @rds_size - size of rds raw data
+ *  @getfreq - function pointer, AF need get current freq
+ */
+fm_s32 rds_parser(rds_t *rds_dst, struct rds_rx_t *rds_raw, fm_s32 rds_size, fm_u16(*getfreq)(void))
+{
+    fm_s32 ret = 0;
+    //block_data[0] = blockA,   block_data[1] = blockB, block_data[2] = blockC,   block_data[3] = blockD,
+    //block_data[4] = CRC,      block_data[5] = CBC
+    fm_u16 block_data[6];
+    fm_u8 GroupType, SubType = 0;
+    fm_s32 rds_cnt = 0;
+    fm_s32 i = 0;
+    fm_bool dirty = fm_false;
+    //target buf to fill the result in
+    fm_u16 *event = &rds_dst->event_status;
+    fm_u32 *flag = &rds_dst->RDSFlag.flag_status;
+
+    FMR_ASSERT(getfreq);
+    rds_get_freq = getfreq;
+
+    ret = rds_cnt_get(rds_raw, rds_size, &rds_cnt);
+
+    if (ret) {
+        WCN_DBG(FM_WAR | RDSC, "get cnt err[ret=%d]\n", ret);
+        return ret;
+    }
+
+    while (rds_cnt > 0) {
+        ret = rds_grp_get(&block_data[0], rds_raw, i);
+
+        if (ret) {
+            WCN_DBG(FM_WAR | RDSC, "get group err[ret=%d]\n", ret);
+            goto do_next;
+        }
+
+        ret = rds_grp_type_get(block_data[4], block_data[1], &GroupType, &SubType);
+
+        if (ret) {
+            WCN_DBG(FM_WAR | RDSC, "get group type err[ret=%d]\n", ret);
+            goto do_next;
+        }
+
+        ret = rds_grp_counter_add(GroupType, SubType, &rds_dst->gc);
+
+        ret = rds_grp_pi_get(block_data[4], block_data[0], &rds_dst->PI, &dirty);
+
+        if (ret) {
+            WCN_DBG(FM_WAR | RDSC, "get group pi err[ret=%d]\n", ret);
+            goto do_next;
+        } else if (dirty == fm_true) {
+            ret = rds_event_set(event, RDS_EVENT_PI_CODE); //yes, we got new PI code
+        }
+
+        ret = rds_grp_pty_get(block_data[4], block_data[1], &rds_dst->PTY, &dirty);
+
+        if (ret) {
+            WCN_DBG(FM_WAR | RDSC, "get group pty err[ret=%d]\n", ret);
+            goto do_next;
+        } else if (dirty == fm_true) {
+            ret = rds_event_set(event, RDS_EVENT_PTY_CODE); // yes, we got new PTY code
+        }
+
+        ret = rds_grp_tp_get(block_data[4], block_data[1], &rds_dst->RDSFlag.TP, &dirty);
+
+        if (ret) {
+            WCN_DBG(FM_WAR | RDSC, "get group tp err[ret=%d]\n", ret);
+            goto do_next;
+        } else if (dirty == fm_true) {
+            ret = rds_event_set(event, RDS_EVENT_FLAGS); // yes, we got new TP code
+            ret = rds_flag_set(flag, RDS_FLAG_IS_TP);
+        }
+
+        switch (GroupType) {
+        case 0:
+
+            if ((ret = rds_retrieve_g0(&block_data[0], SubType, rds_dst)))
+                goto do_next;
+
+            break;
+        case 1:
+
+            if ((ret = rds_retrieve_g1(&block_data[0], SubType, rds_dst)))
+                goto do_next;
+
+            break;
+        case 2:
+
+            if ((ret = rds_retrieve_g2(&block_data[0], SubType, rds_dst)))
+                goto do_next;
+
+            break;
+        case 4:
+
+            if ((ret = rds_retrieve_g4(&block_data[0], SubType, rds_dst)))
+                goto do_next;
+
+            break;
+        case 14:
+
+            if ((ret = rds_retrieve_g14(&block_data[0], SubType, rds_dst)))
+                goto do_next;
+
+            break;
+        default:
+            break;
+        }
+
+do_next:
+
+        if (ret && (ret != -FM_ECRC)) {
+            WCN_DBG(FM_ERR | RDSC, "parsing err[ret=%d]\n", ret);
+            return ret;
+        }
+
+        rds_cnt--;
+        i++;
+    }
+
+    return ret;
+}
+
+
diff --git a/drivers/mtk_wcn_combo/drv_fm/core/fm_utils.c b/drivers/mtk_wcn_combo/drv_fm/core/fm_utils.c
new file mode 100755 (executable)
index 0000000..0f52f4e
--- /dev/null
@@ -0,0 +1,685 @@
+/* fm_event.c
+ *
+ * (C) Copyright 2011
+ * MediaTek <www.MediaTek.com>
+ * Hongcheng <hongcheng.xia@MediaTek.com>
+ *
+ * FM Radio Driver -- a common event
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <asm/uaccess.h>
+#include <linux/semaphore.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+
+#include "fm_typedef.h"
+#include "fm_dbg.h"
+#include "fm_err.h"
+#include "fm_stdlib.h"
+#include "fm_utils.h"
+
+static fm_u32 fm_event_send(struct fm_flag_event* thiz, fm_u32 mask)
+{
+    thiz->flag |= mask;
+    //WCN_DBG(FM_DBG|MAIN, "%s set 0x%08x\n", thiz->name, thiz->flag);
+    wake_up((wait_queue_head_t*)(thiz->priv));
+
+    return thiz->flag;
+}
+
+static fm_s32 fm_event_wait(struct fm_flag_event* thiz, fm_u32 mask)
+{
+    return wait_event_interruptible(*(wait_queue_head_t*)(thiz->priv), ((thiz->flag & mask) == mask));
+}
+
+/**
+ * fm_event_check - sleep until a condition gets true or a timeout elapses
+ * @thiz: the pointer of current object
+ * @mask: bitmap in fm_u32
+ * @timeout: timeout, in jiffies
+ *
+ * fm_event_set() has to be called after changing any variable that could
+ * change the result of the wait condition.
+ *
+ * The function returns 0 if the @timeout elapsed, and the remaining
+ * jiffies if the condition evaluated to true before the timeout elapsed.
+ */
+long fm_event_wait_timeout(struct fm_flag_event* thiz, fm_u32 mask, long timeout)
+{
+    return wait_event_timeout(*((wait_queue_head_t*)(thiz->priv)), ((thiz->flag & mask) == mask), timeout*HZ);
+}
+
+static fm_u32 fm_event_clr(struct fm_flag_event* thiz, fm_u32 mask)
+{
+    thiz->flag &= ~mask;
+    //WCN_DBG(FM_DBG|MAIN, "%s clr 0x%08x\n", thiz->name, thiz->flag);
+    return thiz->flag;
+}
+
+static fm_u32 fm_event_get(struct fm_flag_event* thiz)
+{
+    return thiz->flag;
+
+}
+
+static fm_u32 fm_event_rst(struct fm_flag_event* thiz)
+{
+    return thiz->flag = 0;
+}
+
+struct fm_flag_event* fm_flag_event_create(const fm_s8 *name) 
+{
+    struct fm_flag_event *tmp;
+    wait_queue_head_t *wq;
+
+    if (!(tmp = fm_zalloc(sizeof(struct fm_flag_event)))) {
+        WCN_DBG(FM_ALT | MAIN, "fm_zalloc(fm_event) -ENOMEM\n");
+        return NULL;
+    }
+
+    if (!(wq = fm_zalloc(sizeof(wait_queue_head_t)))) {
+        WCN_DBG(FM_ALT | MAIN, "fm_zalloc(wait_queue_head_t) -ENOMEM\n");
+        fm_free(tmp);
+        return NULL;
+    }
+
+    fm_memcpy(tmp->name, name, (strlen(name)>FM_NAME_MAX)?(FM_NAME_MAX):(strlen(name)));
+    tmp->priv = wq;
+    init_waitqueue_head(wq);
+    tmp->ref = 0;
+
+    tmp->send = fm_event_send;
+    tmp->wait = fm_event_wait;
+    tmp->wait_timeout = fm_event_wait_timeout;
+    tmp->clr = fm_event_clr;
+    tmp->get = fm_event_get;
+    tmp->rst = fm_event_rst;
+
+    tmp->rst(tmp);  //set flag to 0x00000000
+
+    return tmp;
+}
+
+fm_s32 fm_flag_event_get(struct fm_flag_event *thiz)
+{
+    FMR_ASSERT(thiz);
+    thiz->ref++;
+    return 0;
+}
+
+fm_s32 fm_flag_event_put(struct fm_flag_event *thiz)
+{
+    FMR_ASSERT(thiz);
+    thiz->ref--;
+
+    if (thiz->ref == 0) {
+        fm_free(thiz->priv);
+        fm_free(thiz);
+        return 0;
+    } else if (thiz->ref > 0) {
+        return -FM_EINUSE;
+    } else {
+        return -FM_EPARA;
+    }
+}
+
+//fm lock methods
+static fm_s32 fm_lock_try(struct fm_lock *thiz,fm_s32 retryCnt)
+{
+    fm_s32 retry_cnt = 0;
+    struct semaphore *sem;
+    struct task_struct *task = current;
+    FMR_ASSERT(thiz);
+    FMR_ASSERT(thiz->priv);
+
+    while(down_trylock((struct semaphore*)thiz->priv))
+    {
+        WCN_DBG(FM_WAR | MAIN, "down_trylock failed\n");
+        if(++retry_cnt < retryCnt)
+        {
+            WCN_DBG(FM_WAR | MAIN,"[retryCnt=%d]\n", retry_cnt);
+            msleep_interruptible(50); 
+            continue;
+        }
+        else
+        {
+            WCN_DBG(FM_CRT | MAIN,"down_trylock retry failed\n");
+                       return -FM_ELOCK;
+        }    
+    }
+
+    sem = (struct semaphore*)thiz->priv;
+    WCN_DBG(FM_NTC | MAIN, "%s --->trylock, cnt=%d, pid=%d\n", thiz->name, (int)sem->count, task->pid);
+    return 0;
+}
+
+//fm try lock methods
+static fm_s32 fm_lock_lock(struct fm_lock *thiz)
+{
+    struct semaphore *sem;
+    struct task_struct *task = current;
+    FMR_ASSERT(thiz);
+    FMR_ASSERT(thiz->priv);
+
+    if (down_interruptible((struct semaphore*)thiz->priv)) {
+        WCN_DBG(FM_CRT | MAIN, "get mutex failed\n");
+        return -FM_ELOCK;
+    }
+
+    sem = (struct semaphore*)thiz->priv;
+    WCN_DBG(FM_NTC | MAIN, "%s --->lock, cnt=%d, pid=%d\n", thiz->name, (int)sem->count, task->pid);
+    return 0;
+}
+
+static fm_s32 fm_lock_unlock(struct fm_lock *thiz)
+{
+    struct semaphore *sem;
+    struct task_struct *task = current;
+    FMR_ASSERT(thiz);
+    FMR_ASSERT(thiz->priv);
+    sem = (struct semaphore*)thiz->priv;
+    WCN_DBG(FM_NTC | MAIN, "%s <---unlock, cnt=%d, pid=%d\n", thiz->name, (int)sem->count + 1, task->pid);
+    up((struct semaphore*)thiz->priv);
+    return 0;
+}
+
+struct fm_lock* fm_lock_create(const fm_s8 *name) 
+{
+    struct fm_lock *tmp;
+    struct semaphore *mutex;
+
+    if (!(tmp = fm_zalloc(sizeof(struct fm_lock)))) {
+        WCN_DBG(FM_ALT | MAIN, "fm_zalloc(fm_lock) -ENOMEM\n");
+        return NULL;
+    }
+
+    if (!(mutex = fm_zalloc(sizeof(struct semaphore)))) {
+        WCN_DBG(FM_ALT | MAIN, "fm_zalloc(struct semaphore) -ENOMEM\n");
+        fm_free(tmp);
+        return NULL;
+    }
+
+    tmp->priv = mutex;
+    sema_init(mutex, 1);
+    tmp->ref = 0;
+    fm_memcpy(tmp->name, name, (strlen(name)>FM_NAME_MAX)?(FM_NAME_MAX):(strlen(name)));
+
+    tmp->lock = fm_lock_lock;
+    tmp->trylock = fm_lock_try;
+    tmp->unlock = fm_lock_unlock;
+
+    return tmp;
+}
+
+fm_s32 fm_lock_get(struct fm_lock *thiz)
+{
+    FMR_ASSERT(thiz);
+    thiz->ref++;
+    return 0;
+}
+
+fm_s32 fm_lock_put(struct fm_lock *thiz)
+{
+    FMR_ASSERT(thiz);
+    thiz->ref--;
+
+    if (thiz->ref == 0) {
+        fm_free(thiz->priv);
+        fm_free(thiz);
+        return 0;
+    } else if (thiz->ref > 0) {
+        return -FM_EINUSE;
+    } else {
+        return -FM_EPARA;
+    }
+}
+
+//fm lock methods
+static fm_s32 fm_spin_lock_lock(struct fm_lock *thiz)
+{
+    struct task_struct *task = current;
+    FMR_ASSERT(thiz);
+    FMR_ASSERT(thiz->priv);
+
+       spin_lock_bh((spinlock_t *)thiz->priv);
+
+    WCN_DBG(FM_NTC | MAIN, "%s --->lock pid=%d\n", thiz->name, task->pid);
+    return 0;
+}
+
+static fm_s32 fm_spin_lock_unlock(struct fm_lock *thiz)
+{
+    struct task_struct *task = current;
+    FMR_ASSERT(thiz);
+    FMR_ASSERT(thiz->priv);
+
+    WCN_DBG(FM_NTC | MAIN, "%s <---unlock, pid=%d\n", thiz->name, task->pid);
+    spin_unlock_bh((spinlock_t *)thiz->priv);
+    return 0;
+}
+
+struct fm_lock* fm_spin_lock_create(const fm_s8 *name) 
+{
+       struct fm_lock *tmp;
+       spinlock_t *spin_lock;
+
+    if (!(tmp = fm_zalloc(sizeof(struct fm_lock)))) {
+        WCN_DBG(FM_ALT | MAIN, "fm_zalloc(fm_lock) -ENOMEM\n");
+        return NULL;
+    }
+
+    if (!(spin_lock = fm_zalloc(sizeof(spinlock_t)))) {
+        WCN_DBG(FM_ALT | MAIN, "fm_zalloc(spinlock_t) -ENOMEM\n");
+        fm_free(tmp);
+        return NULL;
+    }
+
+    tmp->priv = spin_lock;
+    spin_lock_init(spin_lock);
+    tmp->ref = 0;
+    fm_memcpy(tmp->name, name, (strlen(name)>FM_NAME_MAX)?(FM_NAME_MAX):(strlen(name)));
+
+    tmp->lock = fm_spin_lock_lock;
+    tmp->unlock = fm_spin_lock_unlock;
+
+    return tmp;
+}
+
+
+fm_s32 fm_spin_lock_get(struct fm_lock *thiz)
+{
+    FMR_ASSERT(thiz);
+    thiz->ref++;
+    return 0;
+}
+
+fm_s32 fm_spin_lock_put(struct fm_lock *thiz)
+{
+    FMR_ASSERT(thiz);
+    thiz->ref--;
+
+    if (thiz->ref == 0) {
+        fm_free(thiz->priv);
+        fm_free(thiz);
+        return 0;
+    } else if (thiz->ref > 0) {
+        return -FM_EINUSE;
+    } else {
+        return -FM_EPARA;
+    }
+}
+
+/*
+ * fm timer
+ *
+ */
+static fm_s32 fm_timer_init(struct fm_timer *thiz, void (*timeout)(unsigned long data), unsigned long data, signed long time, fm_s32 flag)
+{
+    struct timer_list *timerlist = (struct timer_list*)thiz->priv;
+
+    thiz->flag = flag;
+    thiz->flag &= ~FM_TIMER_FLAG_ACTIVATED;
+    thiz->timeout_func = timeout;
+    thiz->data = data;
+    thiz->timeout_ms = time;
+
+    timerlist->expires  = jiffies + (thiz->timeout_ms) / (1000 / HZ);
+    timerlist->function = thiz->timeout_func;
+    timerlist->data     = (unsigned long)thiz->data;
+
+    return 0;
+}
+
+static fm_s32 fm_timer_start(struct fm_timer *thiz)
+{
+    struct timer_list *timerlist = (struct timer_list*)thiz->priv;
+
+    thiz->flag |= FM_TIMER_FLAG_ACTIVATED;
+    mod_timer(timerlist, jiffies + (thiz->timeout_ms) / (1000 / HZ));
+
+    return 0;
+}
+
+static fm_s32 fm_timer_update(struct fm_timer *thiz)
+{
+    struct timer_list *timerlist = (struct timer_list*)thiz->priv;
+
+    if (thiz->flag & FM_TIMER_FLAG_ACTIVATED) {
+        mod_timer(timerlist, jiffies + (thiz->timeout_ms) / (1000 / HZ));
+        return 0;
+    } else {
+        return 1;
+    }
+}
+
+static fm_s32 fm_timer_stop(struct fm_timer *thiz)
+{
+    struct timer_list *timerlist = (struct timer_list*)thiz->priv;
+
+    thiz->flag &= ~FM_TIMER_FLAG_ACTIVATED;
+    del_timer(timerlist);
+
+    return 0;
+}
+
+static fm_s32 fm_timer_control(struct fm_timer *thiz, enum fm_timer_ctrl cmd, void* arg)
+{
+
+    return 0;
+}
+
+struct fm_timer* fm_timer_create(const fm_s8 *name) 
+{
+    struct fm_timer *tmp;
+    struct timer_list *timerlist;
+
+    if (!(tmp = fm_zalloc(sizeof(struct fm_timer)))) {
+        WCN_DBG(FM_ALT | MAIN, "fm_zalloc(fm_timer) -ENOMEM\n");
+        return NULL;
+    }
+
+    if (!(timerlist = fm_zalloc(sizeof(struct timer_list)))) {
+        WCN_DBG(FM_ALT | MAIN, "fm_zalloc(struct timer_list) -ENOMEM\n");
+        fm_free(tmp);
+        return NULL;
+    }
+
+    init_timer(timerlist);
+
+    fm_memcpy(tmp->name, name, (strlen(name)>FM_NAME_MAX)?(FM_NAME_MAX):(strlen(name)));
+    tmp->priv = timerlist;
+    tmp->ref = 0;
+    tmp->init = fm_timer_init;
+    tmp->start = fm_timer_start;
+    tmp->stop = fm_timer_stop;
+    tmp->update = fm_timer_update;
+    tmp->control = fm_timer_control;
+
+    return tmp;
+}
+
+fm_s32 fm_timer_get(struct fm_timer *thiz)
+{
+    FMR_ASSERT(thiz);
+    thiz->ref++;
+    return 0;
+}
+
+fm_s32 fm_timer_put(struct fm_timer *thiz)
+{
+    FMR_ASSERT(thiz);
+    thiz->ref--;
+
+    if (thiz->ref == 0) {
+        fm_free(thiz->priv);
+        fm_free(thiz);
+        return 0;
+    } else if (thiz->ref > 0) {
+        return -FM_EINUSE;
+    } else {
+        return -FM_EPARA;
+    }
+}
+
+
+/*
+ * FM work thread mechanism
+ */
+static fm_s32 fm_work_init(struct fm_work *thiz, void (*work_func)(unsigned long data), unsigned long data)
+{
+    struct work_struct *sys_work = (struct work_struct*)thiz->priv;
+    work_func_t func;
+
+    thiz->work_func = work_func;
+    thiz->data = data;
+    func = (work_func_t)thiz->work_func;
+
+    INIT_WORK(sys_work, func);
+
+    return 0;
+
+}
+
+struct fm_work* fm_work_create(const fm_s8 *name) 
+{
+    struct fm_work *my_work;
+    struct work_struct *sys_work;
+
+    if (!(my_work = fm_zalloc(sizeof(struct fm_work)))) {
+        WCN_DBG(FM_ALT | MAIN, "fm_zalloc(fm_work) -ENOMEM\n");
+        return NULL;
+    }
+
+    if (!(sys_work = fm_zalloc(sizeof(struct work_struct)))) {
+        WCN_DBG(FM_ALT | MAIN, "fm_zalloc(struct work_struct) -ENOMEM\n");
+        fm_free(my_work);
+        return NULL;
+    }
+
+    fm_memcpy(my_work->name, name, (strlen(name)>FM_NAME_MAX)?(FM_NAME_MAX):(strlen(name)));
+    my_work->priv = sys_work;
+    my_work->init = fm_work_init;
+
+    return my_work;
+}
+
+fm_s32 fm_work_get(struct fm_work *thiz)
+{
+    FMR_ASSERT(thiz);
+    thiz->ref++;
+    return 0;
+}
+
+fm_s32 fm_work_put(struct fm_work *thiz)
+{
+    FMR_ASSERT(thiz);
+    thiz->ref--;
+
+    if (thiz->ref == 0) {
+        fm_free(thiz->priv);
+        fm_free(thiz);
+        return 0;
+    } else if (thiz->ref > 0) {
+        return -FM_EINUSE;
+    } else {
+        return -FM_EPARA;
+    }
+}
+
+
+static fm_s32 fm_workthread_add_work(struct fm_workthread *thiz, struct fm_work *work)
+{
+    FMR_ASSERT(thiz);
+    FMR_ASSERT(work);
+
+    queue_work((struct workqueue_struct*)thiz->priv, (struct work_struct*)work->priv);
+    return 0;
+}
+
+struct fm_workthread* fm_workthread_create(const fm_s8* name) 
+{
+    struct fm_workthread *my_thread;
+    struct workqueue_struct *sys_thread;
+
+    if (!(my_thread = fm_zalloc(sizeof(struct fm_workthread)))) {
+        WCN_DBG(FM_ALT | MAIN, "fm_zalloc(fm_workthread) -ENOMEM\n");
+        return NULL;
+    }
+
+    sys_thread = create_singlethread_workqueue(name);
+
+    fm_memcpy(my_thread->name, name, (strlen(name)>FM_NAME_MAX)?(FM_NAME_MAX):(strlen(name)));
+    my_thread->priv = sys_thread;
+    my_thread->add_work = fm_workthread_add_work;
+
+    return my_thread;
+}
+
+fm_s32 fm_workthread_get(struct fm_workthread *thiz)
+{
+    FMR_ASSERT(thiz);
+    thiz->ref++;
+    return 0;
+}
+
+fm_s32 fm_workthread_put(struct fm_workthread *thiz)
+{
+    FMR_ASSERT(thiz);
+    thiz->ref--;
+
+    if (thiz->ref == 0) {
+        destroy_workqueue((struct workqueue_struct*)thiz->priv);
+        fm_free(thiz);
+        return 0;
+    } else if (thiz->ref > 0) {
+        return -FM_EINUSE;
+    } else {
+        return -FM_EPARA;
+    }
+}
+
+
+fm_s32 fm_fifo_in(struct fm_fifo *thiz, void *item)
+{
+    FMR_ASSERT(item);
+
+    if (thiz->len < thiz->size) {
+        fm_memcpy((thiz->obj.priv + (thiz->item_size * thiz->in)), item, thiz->item_size);
+        thiz->in = (thiz->in + 1) % thiz->size;
+        thiz->len++;
+        //WCN_DBG(FM_DBG | MAIN, "add a new item[len=%d]\n", thiz->len);
+    } else {
+        WCN_DBG(FM_WAR | MAIN, "%s fifo is full\n", thiz->obj.name);
+        return -FM_ENOMEM;
+    }
+
+    return 0;
+}
+
+fm_s32 fm_fifo_out(struct fm_fifo *thiz, void *item)
+{
+    if (thiz->len > 0) {
+        if (item) {
+            fm_memcpy(item, (thiz->obj.priv + (thiz->item_size * thiz->out)), thiz->item_size);
+            fm_memset((thiz->obj.priv + (thiz->item_size * thiz->out)), 0, thiz->item_size);
+        }
+        thiz->out = (thiz->out + 1) % thiz->size;
+        thiz->len--;
+        //WCN_DBG(FM_DBG | MAIN, "del an item[len=%d]\n", thiz->len);
+    } else {
+        WCN_DBG(FM_WAR | MAIN, "%s fifo is empty\n", thiz->obj.name);
+    }
+
+    return 0;
+}
+
+fm_bool fm_fifo_is_full(struct fm_fifo *thiz)
+{
+    return (thiz->len == thiz->size) ? fm_true : fm_false;
+}
+
+fm_bool fm_fifo_is_empty(struct fm_fifo *thiz)
+{
+    return (thiz->len == 0) ? fm_true : fm_false;
+}
+
+fm_s32 fm_fifo_get_total_len(struct fm_fifo *thiz)
+{
+    return thiz->size;
+}
+
+fm_s32 fm_fifo_get_valid_len(struct fm_fifo *thiz)
+{
+    return thiz->len;
+}
+
+fm_s32 fm_fifo_reset(struct fm_fifo *thiz)
+{
+    fm_memset(thiz->obj.priv, 0, thiz->item_size * thiz->size);
+    thiz->in = 0;
+    thiz->out = 0;
+    thiz->len = 0;
+
+    return 0;
+}
+
+struct fm_fifo* fm_fifo_init(struct fm_fifo* fifo, void *buf, const fm_s8 *name, fm_s32 item_size, fm_s32 item_num) 
+{
+    fm_memcpy(fifo->obj.name, name, 20);
+    fifo->size = item_num;
+    fifo->in = 0;
+    fifo->out = 0;
+    fifo->len = 0;
+    fifo->item_size = item_size;
+    fifo->obj.priv = buf;
+
+    fifo->input = fm_fifo_in;
+    fifo->output = fm_fifo_out;
+    fifo->is_full = fm_fifo_is_full;
+    fifo->is_empty = fm_fifo_is_empty;
+    fifo->get_total_len = fm_fifo_get_total_len;
+    fifo->get_valid_len = fm_fifo_get_valid_len;
+    fifo->reset = fm_fifo_reset;
+    
+    WCN_DBG(FM_NTC | LINK, "%s inited\n", fifo->obj.name);
+
+    return fifo;
+}
+
+struct fm_fifo* fm_fifo_create(const fm_s8 *name, fm_s32 item_size, fm_s32 item_num) 
+{
+    struct fm_fifo *tmp;
+    void *buf;
+
+    if (!(tmp = fm_zalloc(sizeof(struct fm_fifo)))) {
+        WCN_DBG(FM_ALT | MAIN, "fm_zalloc(fm_fifo) -ENOMEM\n");
+        return NULL;
+    }
+
+    if (!(buf = fm_zalloc(item_size * item_num))) {
+        WCN_DBG(FM_ALT | MAIN, "fm_zalloc(fm_fifo) -ENOMEM\n");
+        fm_free(tmp);
+        return NULL;
+    }
+
+    tmp = fm_fifo_init(tmp, buf, name, item_size, item_num);
+    
+    WCN_DBG(FM_NTC | LINK, "%s created\n", tmp->obj.name);
+
+    return tmp;
+}
+
+
+fm_s32 fm_fifo_release(struct fm_fifo *fifo) 
+{
+    if (fifo) {
+        WCN_DBG(FM_NTC | LINK, "%s released\n", fifo->obj.name);
+        if (fifo->obj.priv) {
+            fm_free(fifo->obj.priv);
+        }
+        fm_free(fifo);
+    }
+
+    return 0;
+}
+
+
+
diff --git a/drivers/mtk_wcn_combo/drv_fm/cust/mt6620/mt6620_fm_cust_cfg.h b/drivers/mtk_wcn_combo/drv_fm/cust/mt6620/mt6620_fm_cust_cfg.h
new file mode 100755 (executable)
index 0000000..8ff7d19
--- /dev/null
@@ -0,0 +1,133 @@
+/* alps/ALPS_SW/TRUNK/MAIN/alps/kernel/arch/arm/mach-mt6516/include/mach/fm.h
+ *
+ * (C) Copyright 2009
+ * MediaTek <www.MediaTek.com>
+ * William Chung <William.Chung@MediaTek.com>
+ *
+ * MT6516 AR10x0 FM Radio Driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __FM_CUST_CFG_H__
+#define __FM_CUST_CFG_H__
+
+//scan sort algorithm
+enum {
+    FM_SCAN_SORT_NON = 0,
+    FM_SCAN_SORT_UP,
+    FM_SCAN_SORT_DOWN,
+    FM_SCAN_SORT_MAX
+};
+//***********************************FM config for customer ***********************************
+//RX
+#define FMR_RSSI_TH_LONG_MT6620    0x0301      //FM radio long antenna RSSI threshold(11.375dBuV)
+#define FMR_RSSI_TH_SHORT_MT6620   0x02E0      //FM radio short antenna RSSI threshold(-1dBuV)
+#define FMR_CQI_TH_MT6620          0x00E9      //FM radio Channel quality indicator threshold(0x0000~0x00FF)
+//***********************************FM config for engineer ***********************************
+//RX
+#define FMR_MR_TH_MT6620           0x01BD      //FM radio MR threshold
+#if 0
+//*****************************************************************************************
+//***********************************FM config for customer ***********************************
+//*****************************************************************************************
+#define FMR_SEEK_SPACE      1           //FM radio seek space,1:100KHZ; 2:200KHZ
+#define FMR_SCAN_CH_SIZE    40          //FM radio scan max channel size
+#define FMR_BAND            1           //FM radio band, 1:87.5MHz~108.0MHz; 2:76.0MHz~90.0MHz; 3:76.0MHz~108.0MHz; 4:special
+#define FM_SCAN_SORT_SELECT FM_SCAN_SORT_NON
+#define FM_FAKE_CH_NUM      1
+#define FM_FAKE_CH_RSSI     40
+#define FM_FAKE_CH_1        1075
+#define FM_FAKE_CH_2        0
+#define FM_FAKE_CH_3        0
+#define FM_FAKE_CH_4        0
+#define FM_FAKE_CH_5        0
+
+//TX
+#define FMTX_PWR_LEVEL_MAX  120
+
+//*****************************************************************************************
+#define ADDR_SCAN_TH        0xE0        //scan thrshold register
+#define ADDR_CQI_TH         0xE1        //scan CQI register
+
+//TX
+#define FMTX_SCAN_HOLE_LOW  923         //92.3MHz~95.4MHz should not show to user
+#define FMTX_SCAN_HOLE_HIGH 954         //92.3MHz~95.4MHz should not show to user
+//*****************************************************************************************
+
+// errno
+#define FM_SUCCESS      0
+#define FM_FAILED       1
+#define FM_EPARM        2
+#define FM_BADSTATUS    3
+#define FM_TUNE_FAILED  4
+#define FM_SEEK_FAILED  5
+#define FM_BUSY         6
+#define FM_SCAN_FAILED  7
+
+//max scan chl num
+#define FM_MAX_CHL_SIZE FMR_SCAN_CH_SIZE
+// auto HiLo
+#define FM_AUTO_HILO_OFF    0
+#define FM_AUTO_HILO_ON     1
+
+#define FM_CHIP_AR1000 0x1000
+#define FM_CHIP_MT5192 0x91
+#define FM_CHIP_MT5193 0x92
+#define FM_CHIP_MT6616 0x6616
+#define FM_CHIP_MT6626 0x6626
+#define FM_CHIP_MT6628 0x6628
+#define FM_CHIP_MT6620 0x6620
+#define FM_CHIP_UNSUPPORTED 0xffff
+
+// seek threshold
+#define FM_SEEKTH_LEVEL_DEFAULT 4
+#endif
+//RX
+#define FM_RX_RSSI_TH_LONG_MT6620    -296      //FM radio long antenna RSSI threshold(-4dBuV)
+#define FM_RX_RSSI_TH_SHORT_MT6620   -296      //FM radio short antenna RSSI threshold(-4dBuV)
+#define FM_RX_DESENSE_RSSI_MT6620   -245      
+#define FM_RX_PAMD_TH_MT6620          -12     
+#define FM_RX_MR_TH_MT6620           -67      
+#define FM_RX_ATDC_TH_MT6620           219      
+#define FM_RX_PRX_TH_MT6620           64      
+#define FM_RX_SMG_TH_MT6620          6      //FM soft-mute gain threshold
+#define FM_RX_DEEMPHASIS_MT6620       0           //0-50us, China Mainland; 1-75us China Taiwan
+#define FM_RX_OSC_FREQ_MT6620         0           //0-26MHz; 1-19MHz; 2-24MHz; 3-38.4MHz; 4-40MHz; 5-52MHz  
+#if 0
+#define FM_RX_RSSI_TH_LONG_MT6620    0xF2D8      //FM radio long antenna RSSI threshold(-4dBuV)
+#define FM_RX_RSSI_TH_SHORT_MT6620   0xF2D8      //FM radio short antenna RSSI threshold(-4dBuV)
+#define FM_RX_CQI_TH_MT6620          0x00E9      //FM radio Channel quality indicator threshold(0x0000~0x00FF)
+#define FM_RX_MR_TH_MT6620           0x01BD      //FM radio MR threshold
+#define FM_RX_SMG_TH_MT6620          0x4025      //FM soft-mute gain threshold
+#define FM_RX_SEEK_SPACE_MT6620      1           //FM radio seek space,1:100KHZ; 2:200KHZ
+#define FM_RX_SCAN_CH_SIZE_MT6620    40          //FM radio scan max channel size
+#define FM_RX_BAND_MT6620            1           //FM radio band, 1:87.5MHz~108.0MHz; 2:76.0MHz~90.0MHz; 3:76.0MHz~108.0MHz; 4:special
+
+#define FM_RX_SCAN_SORT_SELECT_MT6620 FM_SCAN_SORT_NON
+#define FM_RX_FAKE_CH_NUM_MT6620      1
+#define FM_RX_FAKE_CH_RSSI_MT6620     40
+#define FM_RX_FAKE_CH_1_MT6620        1075
+#define FM_RX_FAKE_CH_2_MT6620        0
+#define FM_RX_FAKE_CH_3_MT6620        0
+#define FM_RX_FAKE_CH_4_MT6620        0
+#define FM_RX_FAKE_CH_5_MT6620        0
+#endif
+//TX
+#define FM_TX_PWR_LEVEL_MAX_MT6620  120  
+#define FM_TX_SCAN_HOLE_LOW_MT6620  923         //92.3MHz~95.4MHz should not show to user
+#define FM_TX_SCAN_HOLE_HIGH_MT6620 954         //92.3MHz~95.4MHz should not show to user
+
+#endif // __FM_CUST_CFG_H__
diff --git a/drivers/mtk_wcn_combo/drv_fm/cust/mt6626/fm_cust_cfg.h b/drivers/mtk_wcn_combo/drv_fm/cust/mt6626/fm_cust_cfg.h
new file mode 100755 (executable)
index 0000000..6637042
--- /dev/null
@@ -0,0 +1,105 @@
+/* 
+ *
+ * (C) Copyright 20011
+ * MediaTek <www.MediaTek.com>
+ * Hongcheng Xia<Hongcheng.Xia@MediaTek.com>
+ *
+ * FM Radio Driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __FM_CUST_CFG_H__
+#define __FM_CUST_CFG_H__
+
+//scan sort algorithm 
+enum{
+    FM_SCAN_SORT_NON = 0,
+    FM_SCAN_SORT_UP,
+    FM_SCAN_SORT_DOWN,
+    FM_SCAN_SORT_MAX
+};
+
+//*****************************************************************************************
+//***********************************FM config for customer: start******************************
+//*****************************************************************************************
+//RX
+#define FM_RX_RSSI_TH_LONG    0xFF01      //FM radio long antenna RSSI threshold(11.375dBuV)
+#define FM_RX_RSSI_TH_SHORT   0xFEE0      //FM radio short antenna RSSI threshold(-1dBuV)
+#define FM_RX_CQI_TH          0x00E9      //FM radio Channel quality indicator threshold(0x0000~0x00FF)
+#define FM_RX_MR_TH           0x01BD      //FM radio MR threshold
+#define FM_RX_SMG_TH          0x4025      //FM soft-mute gain threshold
+#define FM_RX_SEEK_SPACE      1           //FM radio seek space,1:100KHZ; 2:200KHZ
+#define FM_RX_SCAN_CH_SIZE    40          //FM radio scan max channel size
+#define FM_RX_BAND            1           //FM radio band, 1:87.5MHz~108.0MHz; 2:76.0MHz~90.0MHz; 3:76.0MHz~108.0MHz; 4:special
+#define FM_RX_BAND_FREQ_L     875         //FM radio special band low freq(Default 87.5MHz)
+#define FM_RX_BAND_FREQ_H     1080        //FM radio special band high freq(Default 108.0MHz)
+#define FM_RX_SCAN_SORT_SELECT FM_SCAN_SORT_NON
+#define FM_RX_FAKE_CH_NUM      1
+#define FM_RX_FAKE_CH_RSSI     40
+#define FM_RX_FAKE_CH_1        1075
+#define FM_RX_FAKE_CH_2        0
+#define FM_RX_FAKE_CH_3        0
+#define FM_RX_FAKE_CH_4        0
+#define FM_RX_FAKE_CH_5        0
+#define FM_RX_DEEMPHASIS       0           //0-50us, China Mainland; 1-75us China Taiwan
+#define FM_RX_OSC_FREQ         0           //0-26MHz; 1-19MHz; 2-24MHz; 3-38.4MHz; 4-40MHz; 5-52MHz  
+
+//TX
+#define FM_TX_PWR_LEVEL_MAX  120  
+#define FM_TX_SCAN_HOLE_LOW  923         //92.3MHz~95.4MHz should not show to user
+#define FM_TX_SCAN_HOLE_HIGH 954         //92.3MHz~95.4MHz should not show to user
+
+
+//*****************************************************************************************
+//***********************************FM config for customer:end *******************************
+//*****************************************************************************************
+// band
+#define FM_BAND_UNKNOWN 0
+#define FM_BAND_UE      1 // US/Europe band  87.5MHz ~ 108MHz (DEFAULT)
+#define FM_BAND_JAPAN   2 // Japan band      76MHz   ~ 90MHz
+#define FM_BAND_JAPANW  3 // Japan wideband  76MHZ   ~ 108MHz
+#define FM_BAND_SPECIAL 4 // special   band  between 76MHZ   and  108MHz
+#define FM_BAND_DEFAULT FM_BAND_UE
+#define FM_FREQ_MIN  FM_RX_BAND_FREQ_L
+#define FM_FREQ_MAX  FM_RX_BAND_FREQ_H
+#define FM_RAIDO_BAND FM_BAND_UE
+// space
+#define FM_SPACE_UNKNOWN    0
+#define FM_SPACE_100K       1
+#define FM_SPACE_200K       2
+#define FM_SPACE_DEFAULT    FM_RX_SEEK_SPACE
+#define FM_SEEK_SPACE FM_RX_SEEK_SPACE
+//max scan chl num
+#define FM_MAX_CHL_SIZE FM_RX_SCAN_CH_SIZE
+// auto HiLo
+#define FM_AUTO_HILO_OFF    0
+#define FM_AUTO_HILO_ON     1
+// seek direction
+#define FM_SEEK_UP          0
+#define FM_SEEK_DOWN        1
+
+#define FM_CHIP_AR1000 0x1000
+#define FM_CHIP_MT5192 0x91
+#define FM_CHIP_MT5193 0x92
+#define FM_CHIP_MT6616 0x6616
+#define FM_CHIP_MT6626 0x6626
+#define FM_CHIP_MT6628 0x6628
+#define FM_CHIP_MT6620 0x6620
+#define FM_CHIP_UNSUPPORTED 0xffff
+
+// seek threshold
+#define FM_SEEKTH_LEVEL_DEFAULT 4
+#endif // __FM_CUST_CFG_H__
\ No newline at end of file
diff --git a/drivers/mtk_wcn_combo/drv_fm/cust/mt6628/mt6628_fm_cust_cfg.h b/drivers/mtk_wcn_combo/drv_fm/cust/mt6628/mt6628_fm_cust_cfg.h
new file mode 100755 (executable)
index 0000000..e90f3c3
--- /dev/null
@@ -0,0 +1,99 @@
+/* 
+ *
+ * (C) Copyright 20011
+ * MediaTek <www.MediaTek.com>
+ * Hongcheng Xia<Hongcheng.Xia@MediaTek.com>
+ *
+ * FM Radio Driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __FM_CUST_CFG_H__
+#define __FM_CUST_CFG_H__
+
+//scan sort algorithm 
+enum{
+    FM_SCAN_SORT_NON = 0,
+    FM_SCAN_SORT_UP,
+    FM_SCAN_SORT_DOWN,
+    FM_SCAN_SORT_MAX
+};
+/*typedef struct  {
+    fm_s32 short_ana_rssi_th;
+    fm_s32 long_ana_rssi_th;
+    fm_s32 desene_rssi_th;
+    fm_s32 pamd_th;
+    fm_s32 mr_th;
+    fm_s32 atdc_th;
+    fm_u32 prx_th;
+    fm_u32 atdev_th;
+    fm_u16 smg_th;
+    fm_u16 deemphasis;
+    fm_u16 osc_freq;
+}mt6628_fm_rx_cust_cfg;
+
+typedef struct{
+    mt6628_fm_rx_cust_cfg rx_cfg;
+}mt6628_fm_cust_cfg;
+*/
+//*****************************************************************************************
+//***********************************FM config for customer: start******************************
+//*****************************************************************************************
+//RX
+#define FM_RX_RSSI_TH_LONG_MT6628    -296      //FM radio long antenna RSSI threshold(-4dBuV)
+#define FM_RX_RSSI_TH_SHORT_MT6628   -296      //FM radio short antenna RSSI threshold(-4dBuV)
+#define FM_RX_DESENSE_RSSI_MT6628   -258      
+#define FM_RX_PAMD_TH_MT6628          -12     
+#define FM_RX_MR_TH_MT6628           -67      
+#define FM_RX_ATDC_TH_MT6628           3496      
+#define FM_RX_PRX_TH_MT6628           64      
+#define FM_RX_SMG_TH_MT6628          16421      //FM soft-mute gain threshold
+#define FM_RX_DEEMPHASIS_MT6628       0           //0-50us, China Mainland; 1-75us China Taiwan
+#define FM_RX_OSC_FREQ_MT6628         0           //0-26MHz; 1-19MHz; 2-24MHz; 3-38.4MHz; 4-40MHz; 5-52MHz  
+//#define FM_RX_SEEK_SPACE_MT6628      1           //FM radio seek space,1:100KHZ; 2:200KHZ
+//#define FM_RX_SCAN_CH_SIZE_MT6628    40          //FM radio scan max channel size
+//#define FM_RX_BAND_MT6628            1           //FM radio band, 1:87.5MHz~108.0MHz; 2:76.0MHz~90.0MHz; 3:76.0MHz~108.0MHz; 4:special
+//#define FM_RX_SCAN_SORT_SELECT_MT6628 FM_SCAN_SORT_NON
+//#define FM_RX_FAKE_CH_NUM_MT6628      1
+//#define FM_RX_FAKE_CH_RSSI_MT6628     40
+//#define FM_RX_FAKE_CH_1_MT6628        1075
+//#define FM_RX_FAKE_CH_2_MT6628        0
+//#define FM_RX_FAKE_CH_3_MT6628        0
+//#define FM_RX_FAKE_CH_4_MT6628        0
+//#define FM_RX_FAKE_CH_5_MT6628        0
+
+//TX
+//#define FM_TX_PWR_LEVEL_MAX_MT6628  120  
+//#define FM_TX_SCAN_HOLE_LOW_MT6628  923         //92.3MHz~95.4MHz should not show to user
+//#define FM_TX_SCAN_HOLE_HIGH_MT6628 954         //92.3MHz~95.4MHz should not show to user
+
+
+//*****************************************************************************************
+//***********************************FM config for customer:end *******************************
+//*****************************************************************************************
+
+//#define FM_SEEK_SPACE_MT6628 FM_RX_SEEK_SPACE_MT6628
+//max scan chl num
+//#define FM_MAX_CHL_SIZ_MT6628E FM_RX_SCAN_CH_SIZE_MT6628
+// auto HiLo
+#define FM_AUTO_HILO_OFF_MT6628    0
+#define FM_AUTO_HILO_ON_MT6628     1
+
+
+// seek threshold
+#define FM_SEEKTH_LEVEL_DEFAULT_MT6628 4
+
+#endif // __FM_CUST_CFG_H__
diff --git a/drivers/mtk_wcn_combo/drv_fm/inc/fm_config.h b/drivers/mtk_wcn_combo/drv_fm/inc/fm_config.h
new file mode 100755 (executable)
index 0000000..ec79667
--- /dev/null
@@ -0,0 +1,200 @@
+/* fm_config.h
+ *
+ * (C) Copyright 2011
+ * MediaTek <www.MediaTek.com>
+ * hongcheng <hongcheng.xia@MediaTek.com>
+ *
+ * FM Radio Driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __FM_CONFIG_H__
+#define __FM_CONFIG_H__
+
+#include "fm_typedef.h"
+#include "fm_rds.h"
+#include "fm_dbg.h"
+#include "fm_err.h"
+#include "fm_stdlib.h"
+
+// band
+#define FM_BAND_UNKNOWN 0
+#define FM_BAND_UE      1 // US/Europe band  87.5MHz ~ 108MHz (DEFAULT)
+#define FM_BAND_JAPAN   2 // Japan band      76MHz   ~ 90MHz
+#define FM_BAND_JAPANW  3 // Japan wideband  76MHZ   ~ 108MHz
+#define FM_BAND_SPECIAL 4 // special   band  between 76MHZ   and  108MHz
+#define FM_BAND_DEFAULT FM_BAND_UE
+#define FM_RAIDO_BAND FM_BAND_UE
+#define FM_FREQ_MIN  FM_RX_BAND_FREQ_L
+#define FM_FREQ_MAX  FM_RX_BAND_FREQ_H
+
+#ifdef MTK_FM_50KHZ_SUPPORT
+#define FM_UE_FREQ_MIN  8750
+#define FM_UE_FREQ_MAX  10800
+#define FM_JP_FREQ_MIN  7600
+#define FM_JP_FREQ_MAX  10800
+
+#define FM_RX_BAND_FREQ_L     8750         //FM radio special band low freq(Default 87.5MHz)
+#define FM_RX_BAND_FREQ_H     10800        //FM radio special band high freq(Default 108.0MHz)
+//TX
+#define FM_TX_SCAN_HOLE_LOW  9230         //92.3MHz~95.4MHz should not show to user
+#define FM_TX_SCAN_HOLE_HIGH 9540         //92.3MHz~95.4MHz should not show to user
+
+#else
+#define FM_UE_FREQ_MIN  875
+#define FM_UE_FREQ_MAX  1080
+#define FM_JP_FREQ_MIN  760
+#define FM_JP_FREQ_MAX  1080
+
+#define FM_RX_BAND_FREQ_L     875         //FM radio special band low freq(Default 87.5MHz)
+#define FM_RX_BAND_FREQ_H     1080        //FM radio special band high freq(Default 108.0MHz)
+//TX
+#define FM_TX_SCAN_HOLE_LOW  923         //92.30MHz~95.40MHz should not show to user
+#define FM_TX_SCAN_HOLE_HIGH 954         //92.30MHz~95.40MHz should not show to user
+
+#endif //MTK_FM_50KHZ_SUPPORT
+
+// space
+#define FM_SPACE_UNKNOWN    0
+#define FM_SPACE_100K       1
+#define FM_SPACE_200K       2
+#define FM_SPACE_50K        5
+
+#ifdef MTK_FM_50KHZ_SUPPORT
+#define FM_SPACE_DEFAULT    FM_SPACE_50K
+#else
+#define FM_SPACE_DEFAULT    FM_SPACE_100K
+#endif
+
+#define FM_TX_SCAN_UP  (0)
+#define FM_TX_SCAN_DOWN        (1)
+#define FM_TX_SCAN_MAX 10
+#define FM_TX_SCAN_MIN 1
+
+// seek direction
+#define FM_SEEK_UP          0
+#define FM_SEEK_DOWN        1
+
+#define FM_CHIP_AR1000 0x1000
+#define FM_CHIP_MT5192 0x91
+#define FM_CHIP_MT5193 0x92
+#define FM_CHIP_MT6616 0x6616
+#define FM_CHIP_MT6626 0x6626
+#define FM_CHIP_MT6628 0x6628
+#define FM_CHIP_MT6620 0x6620
+#define FM_CHIP_UNSUPPORTED 0xffff
+
+enum fm_cfg_parser_state {
+    FM_CFG_STAT_NONE = 0,
+    FM_CFG_STAT_GROUP,
+    FM_CFG_STAT_KEY,
+    FM_CFG_STAT_VALUE,
+    FM_CFG_STAT_COMMENT
+};
+
+typedef enum fm_cfg_parser_state fm_cfg_parser_state_t;
+
+#define COMMENT_CHAR '#'
+#define DELIMIT_CHAR '='
+
+#define isspace(a) ((a) == 0x20)
+
+#define FAKE_CH_MAX 10
+#define FM_CUST_CFG_PATH "/etc/fm_cust.cfg"
+
+struct fm_rx_cust_cfg {
+    fm_s32 desene_rssi_th;
+    fm_s32 pamd_th;
+    fm_s32 mr_th;
+    fm_s32 atdc_th;
+    fm_s32 prx_th;
+    fm_s32 atdev_th;
+    fm_s32 short_ana_rssi_th;
+    fm_s32 long_ana_rssi_th;
+    fm_s32 cqi_th;
+//    fm_u16 mr_th;
+    fm_s32 smg_th;
+    fm_s32 scan_ch_size;
+    fm_s32 seek_space;
+    fm_s32 band;
+    fm_s32 band_freq_l;
+    fm_s32 band_freq_h;
+    fm_s32 scan_sort;
+    fm_s32 fake_ch[FAKE_CH_MAX];
+    fm_s32 fake_ch_num;
+    fm_s32 fake_ch_rssi_th;
+    fm_s32 deemphasis;
+    fm_s32 osc_freq;
+};
+
+struct fm_tx_cust_cfg {
+    fm_s32 scan_hole_low;
+    fm_s32 scan_hole_high;
+    fm_s32 power_level;
+};
+
+typedef struct{
+    struct fm_rx_cust_cfg rx_cfg;
+    struct fm_tx_cust_cfg tx_cfg;
+}fm_cust_cfg;
+
+enum fm_cust_cfg_op {
+    FM_CFG_RX_RSSI_TH_LONG = 0,
+    FM_CFG_RX_RSSI_TH_SHORT,
+    FM_CFG_RX_CQI_TH,
+    FM_CFG_RX_MR_TH,
+    FM_CFG_RX_SMG_TH,
+    FM_CFG_RX_SCAN_CH_SIZE,
+    FM_CFG_RX_SEEK_SPACE,
+    FM_CFG_RX_BAND,
+    FM_CFG_RX_BAND_FREQ_L,
+    FM_CFG_RX_BAND_FREQ_H,
+    FM_CFG_RX_SCAN_SORT,
+    FM_CFG_RX_FAKE_CH_NUM,
+    FM_CFG_RX_FAKE_CH_RSSI,
+    FM_CFG_RX_FAKE_CH,
+    FM_CFG_RX_DEEMPHASIS,
+    FM_CFG_RX_OSC_FREQ,
+
+    FM_CFG_TX_SCAN_HOLE_LOW,
+    FM_CFG_TX_SCAN_HOLE_HIGH,
+    FM_CFG_TX_PWR_LEVEL,
+    FM_CFG_MAX
+};
+
+typedef fm_s32(*CFG_HANDLER)(fm_s8 *grp, fm_s8 *key, fm_s8 *val, fm_cust_cfg *cfg);
+extern fm_s32 to_upper_n(fm_s8 *str, fm_s32 len);
+extern fm_s32 check_hex_str(fm_s8 *str, fm_s32 len);
+extern fm_s32 check_dec_str(fm_s8 *str, fm_s32 len);
+extern fm_s32 ascii_to_hex(fm_s8 *in_ascii, fm_u16 *out_hex);
+extern fm_s32 ascii_to_dec(fm_s8 *in_ascii, fm_s32 *out_dec);
+extern fm_s32 trim_string(fm_s8 **start);
+extern fm_s32 trim_path(fm_s8 **start);
+extern fm_s32 cfg_parser(fm_s8 *buffer, CFG_HANDLER handler, fm_cust_cfg *cfg);
+extern fm_s32 cfg_item_match(fm_s8 *src_key, fm_s8 *src_val, fm_s8 *dst_key, fm_s32 *dst_val);
+
+extern fm_s32 fm_cust_config(const fm_s8 *filepath);
+extern fm_u16 fm_cust_config_fetch(enum fm_cust_cfg_op op_code);
+#ifdef MT6628_FM
+extern fm_s32 MT6628fm_cust_config_setup(const fm_s8 *filepath);
+extern fm_u16 MT6628fm_cust_config_fetch(enum fm_cust_cfg_op op_code);
+#endif
+#ifdef MT6620_FM       
+extern fm_s32 MT6620fm_cust_config_setup(const fm_s8 *filepath);
+extern fm_u16 MT6620fm_cust_config_fetch(enum fm_cust_cfg_op op_code);
+#endif
+#endif //__FM_CONFIG_H__
+
diff --git a/drivers/mtk_wcn_combo/drv_fm/inc/fm_dbg.h b/drivers/mtk_wcn_combo/drv_fm/inc/fm_dbg.h
new file mode 100755 (executable)
index 0000000..16d41b7
--- /dev/null
@@ -0,0 +1,57 @@
+#ifndef __FM_DBG_H__
+#define __FM_DBG_H__
+
+#include <linux/kernel.h> //for printk()
+
+//DBG zone
+#define BASE   4
+#define MAIN   (1 << (BASE+0))
+#define LINK   (1 << (BASE+1))
+#define EINT   (1 << (BASE+2))
+#define CHIP   (1 << (BASE+3))
+#define RDSC   (1 << (BASE+4))
+#define G0             (1 << (BASE+5))
+#define G1             (1 << (BASE+6))
+#define G2             (1 << (BASE+7))
+#define G3             (1 << (BASE+8))
+#define G4             (1 << (BASE+9))
+#define G14            (1 << (BASE+10))
+#define RAW            (1 << (BASE+11))
+#define OPEN   (1 << (BASE+12))
+#define IOCTL  (1 << (BASE+13))
+#define READ_  (1 << (BASE+14))
+#define CLOSE  (1 << (BASE+15))
+#define CQI     (1 << (BASE+16))
+#define ALL            0xfffffff0
+
+//DBG level
+#define L0 0x00000000 // EMERG, system will crush 
+#define L1 0x00000001 // ALERT, need action in time
+#define L2 0x00000002 // CRIT, important HW or SW operation failed 
+#define L3 0x00000003 // ERR, normal HW or SW ERR 
+#define L4 0x00000004 // WARNING, importan path or somewhere may occurs err
+#define L5 0x00000005 // NOTICE, normal case 
+#define L6 0x00000006 // INFO, print info if need 
+#define L7 0x00000007 // DEBUG, for debug info
+
+#define FM_EMG L0
+#define FM_ALT L1
+#define FM_CRT L2
+#define FM_ERR L3
+#define FM_WAR L4
+#define FM_NTC L5
+#define FM_INF L6
+#define FM_DBG L7
+
+extern fm_u32 g_dbg_level;
+#define WCN_DBG(flag, fmt, args...) \
+       do { \
+               if ((((flag)&0x0000000f)<=(g_dbg_level&0x0000000f)) && ((flag)&0xfffffff0)& g_dbg_level) { \
+                       printk(KERN_ALERT "[" #flag "]" fmt, ## args); \
+               } \
+       } while(0)
+
+
+
+#endif //__FM_DBG_H__
+
diff --git a/drivers/mtk_wcn_combo/drv_fm/inc/fm_eint.h b/drivers/mtk_wcn_combo/drv_fm/inc/fm_eint.h
new file mode 100755 (executable)
index 0000000..9ce420a
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef __FM_EINT_H__
+#define __FM_EINT_H__
+
+#include "fm_typedef.h"
+
+enum{
+       FM_EINT_PIN_EINT_MODE,
+       FM_EINT_PIN_GPIO_MODE,
+       FM_EINT_PIN_MAX_MODE
+};
+
+extern fm_s32 fm_enable_eint(void);
+extern fm_s32 fm_disable_eint(void);
+extern fm_s32 fm_request_eint(void (*parser)(void));  
+extern fm_s32 fm_eint_pin_cfg(fm_s32 mode);
+
+#endif //__FM_EINT_H__
+
diff --git a/drivers/mtk_wcn_combo/drv_fm/inc/fm_err.h b/drivers/mtk_wcn_combo/drv_fm/inc/fm_err.h
new file mode 100755 (executable)
index 0000000..c5f31d4
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef __FM_ERR_H__
+#define __FM_ERR_H__
+
+#include <linux/kernel.h> //for printk()
+
+#define FM_ERR_BASE 1000
+typedef enum fm_drv_err_t {
+    FM_EOK = FM_ERR_BASE,
+    FM_EBUF,
+    FM_EPARA,
+    FM_ELINK,
+    FM_ELOCK,
+    FM_EFW,
+    FM_ECRC,
+    FM_EWRST, //wholechip reset
+    FM_ESRST, //subsystem reset
+    FM_EPATCH,
+    FM_ENOMEM,
+    FM_EINUSE, //other client is using this object
+    FM_EMAX
+} fm_drv_err_t;
+
+#define FMR_ASSERT(a) { \
+                       if ((a) == NULL) { \
+                               printk("%s,invalid pointer\n", __func__);\
+                               return -FM_EPARA; \
+                       } \
+               }
+
+#endif //__FM_ERR_H__
+
diff --git a/drivers/mtk_wcn_combo/drv_fm/inc/fm_interface.h b/drivers/mtk_wcn_combo/drv_fm/inc/fm_interface.h
new file mode 100755 (executable)
index 0000000..5a5daa8
--- /dev/null
@@ -0,0 +1,222 @@
+#ifndef __FM_INTERFACE_H__
+#define __FM_INTERFACE_H__
+
+#include <linux/cdev.h>
+#include <linux/workqueue.h>
+
+#include "fm_typedef.h"
+#include "fm_rds.h"
+#include "fm_utils.h"
+
+/******************************************************************************
+ * STRUCTURE DEFINITIONS
+ *****************************************************************************/
+enum fm_op_state {
+    FM_STA_STOP = 0,
+    FM_STA_PLAY = 1,
+    FM_STA_TUNE = 2,
+    FM_STA_SEEK = 3,
+    FM_STA_SCAN = 4,
+    FM_STA_RAMPDOWN = 5,
+    FM_STA_UNKOWN = 100,
+    FM_STA_MAX
+};
+
+enum fm_pwr_state {
+    FM_PWR_OFF = 0,
+    FM_PWR_RX_ON = 1,
+    FM_PWR_TX_ON = 2,
+    FM_PWR_MAX
+};
+
+enum fm_audio_path {
+    FM_AUD_ANALOG = 0,  //analog: line in
+    FM_AUD_DIGITAL = 1, //digital: I2S
+    FM_AUD_MAX
+};
+
+enum fm_antenna_type {
+    FM_ANA_LONG = 0,    //long antenna
+    FM_ANA_SHORT = 1,   //short antenna
+    FM_ANA_MAX
+};
+
+struct fm_hw_info {
+    fm_s32 chip_id; //chip ID, eg. 6620
+    fm_s32 eco_ver; //chip ECO version, eg. E3
+    fm_s32 rom_ver; //FM DSP rom code version, eg. V2
+    fm_s32 patch_ver; //FM DSP patch version, eg. 1.11
+    fm_s32 reserve;
+};
+
+typedef struct fm_i2s_info {
+    fm_s32 status;
+    fm_s32 mode;
+    fm_s32 rate;
+} fm_i2s_info_t;
+
+
+struct fm_platform {
+    struct cdev cdev;
+    dev_t dev_t;
+    struct class *cls;
+    struct device *dev;
+};
+
+struct fm {
+    //chip info
+    fm_u16 chip_id;                 //chip id, such as 6616/6620/6626/6628
+    fm_u16 device_id;               //chip version
+    //basic run time info
+    fm_s32 ref;                     //fm driver can be multi opened
+    fm_bool chipon;                 //Chip power state
+    enum fm_pwr_state pwr_sta;      //FM module power state
+    enum fm_op_state op_sta;        //current operation state: tune, seek, scan ...
+    enum fm_audio_path aud_path;    //I2S or Analog
+    fm_s32 vol;                     //current audio volume from chip side
+    fm_bool mute;                   // true: mute, false: playing
+    fm_bool rds_on;                 // true: on, false: off
+    enum fm_antenna_type ana_type;  //long/short antenna
+    fm_bool via_bt;                 // true: fm over bt controller; false: fm over host
+    fm_u16 min_freq;                // for UE, 875KHz
+    fm_u16 max_freq;                // for UE, 1080KHz
+    fm_u16 cur_freq;                //current frequency
+    fm_u8 band;                     // UE/JAPAN/JPANWD
+    /*FM Tx*/
+    fm_u32 vcoon;//TX VCO tracking ON duiration(ms)
+    fm_u32 vcooff;//TX RTC VCO tracking interval(s)
+    fm_u32 txpwrctl;//TX power contrl interval(s)
+    fm_u32 tx_pwr;
+    fm_bool rdstx_on;                 //false:rds tx off, true:rds tx on
+    //RDS data
+    struct fm_flag_event *rds_event;//pointer to rds event
+    struct rds_t *pstRDSData;       //rds spec data buffer
+    //platform data
+    struct fm_platform platform;    //platform related members
+
+    struct fm_workthread *eint_wkthd;
+    struct fm_workthread *timer_wkthd;
+    struct fm_work *eint_wk;
+    struct fm_work *rds_wk;
+    struct fm_work *rst_wk; //work for subsystem reset
+    //Tx
+    struct fm_work *fm_tx_desense_wifi_work;
+    struct fm_work *fm_tx_power_ctrl_work;
+    
+};
+
+struct fm_callback {
+    //call backs
+    fm_u16(*cur_freq_get)(void);
+    fm_s32(*cur_freq_set)(fm_u16 new_freq);
+//    fm_u16(*chan_para_get)(fm_u16 freq);    //get channel parameter, HL side/ FA / ATJ
+};
+
+struct fm_basic_interface {
+    //mt66x6 lib interfaces
+    fm_s32(*low_pwr_wa)(fm_s32 onoff);
+    fm_s32(*pwron)(fm_s32 data);
+    fm_s32(*pwroff)(fm_s32 data);
+    fm_s32(*msdelay)(fm_u32 val);
+    fm_s32(*usdelay)(fm_u32 val);
+    fm_s32(*read)(fm_u8 addr, fm_u16 *val);
+    fm_s32(*write)(fm_u8 addr, fm_u16 val);
+    fm_s32(*setbits)(fm_u8 addr, fm_u16 bits, fm_u16 msk);
+    fm_u16(*chipid_get)(void);
+    fm_s32(*mute)(fm_bool mute);
+    fm_s32(*rampdown)(void);
+    fm_s32(*pwrupseq)(fm_u16 *chip_id, fm_u16 *device_id);
+    fm_s32(*pwrdownseq)(void);
+    fm_bool(*setfreq)(fm_u16 freq);
+    fm_bool(*seek)(fm_u16 min_freq, fm_u16 max_freq, fm_u16 *freq, fm_u16 dir, fm_u16 space);
+    fm_s32(*seekstop)(void);
+    fm_bool(*scan)(fm_u16 min_freq, fm_u16 max_freq, fm_u16 *freq, fm_u16 *tbl, fm_u16 *tblsize, fm_u16 dir, fm_u16 space);
+    fm_bool(*jammer_scan)(fm_u16 min_freq, fm_u16 max_freq, fm_u16 *freq, fm_u16 *tbl, fm_u16 *tblsize, fm_u16 dir, fm_u16 space);
+    fm_s32(*cqi_get)(fm_s8 *buf, fm_s32 buf_len);
+    fm_s32(*scanstop)(void);
+    fm_s32(*rssiget)(fm_s32 *rssi);
+    fm_s32(*volset)(fm_u8 vol);
+    fm_s32(*volget)(fm_u8 *vol);
+    fm_s32(*dumpreg)(void);
+    fm_bool(*msget)(fm_u16 *ms);  //mono/stereo indicator get
+    fm_s32(*msset)(fm_s32 ms);  //mono/stereo force set
+    fm_bool(*pamdget)(fm_u16 *pamd);
+    fm_bool(*em)(fm_u16 group, fm_u16 item, fm_u32 val);
+    fm_s32(*anaswitch)(fm_s32 ana);
+    fm_s32(*anaget)(void);
+    fm_s32(*caparray_get)(fm_s32 *ca);
+    fm_s32(*i2s_set)(fm_s32 onoff, fm_s32 mode, fm_s32 sample);
+    fm_s32(*i2s_get)(fm_s32 *ponoff, fm_s32 *pmode, fm_s32 *psample);
+    fm_s32(*hwinfo_get)(struct fm_hw_info *req);
+    fm_s32(*is_dese_chan)(fm_u16 freq);             // check if this is a de-sense channel
+    fm_s32(*softmute_tune)(fm_u16 freq,fm_s32 *rssi,fm_bool *valid);
+    fm_s32(*desense_check)(fm_u16 freq,fm_s32 rssi);             // check if this is a valid channel
+    fm_s32(*get_freq_cqi)(fm_u16 freq,fm_s32 *cqi);
+    fm_s32(*cqi_log)(fm_s32 min_freq, fm_s32 max_freq,fm_s32 space, fm_s32 cnt);//cqi log tool
+    fm_s32(*fm_via_bt)(fm_bool flag);//fm over BT:1:enable,0:disable
+    /*tx function*/
+    fm_s32(*tx_support)(fm_s32 *sup);
+    fm_s32(*rdstx_enable)(fm_s32 *flag);
+    fm_bool(*tune_tx)(fm_u16 freq);
+    fm_s32(*pwrupseq_tx)(void);
+    fm_s32(*pwrdownseq_tx)(void);
+    fm_s32 (*tx_pwr_ctrl)(fm_u16 freq, fm_s32 *ctr);
+    fm_s32 (*rtc_drift_ctrl)(fm_u16 freq, fm_s32 *ctr);
+    fm_s32 (*tx_desense_wifi)(fm_u16 freq, fm_s32 *ctr);
+    fm_s32 (*tx_scan)(fm_u16 min_freq, fm_u16 max_freq,fm_u16 *pFreq,fm_u16 *pScanTBL,fm_u16 *ScanTBLsize,fm_u16 scandir,fm_u16 space);
+};
+
+struct fm_rds_interface {
+    //rds lib interfaces
+    fm_s32(*rds_blercheck)(rds_t *dst);
+    fm_bool(*rds_onoff)(rds_t *dst, fm_bool onoff);
+    fm_s32(*rds_parser)(rds_t *rds_dst, struct rds_rx_t *rds_raw, fm_s32 rds_size, fm_u16(*getfreq)(void));
+    fm_u16(*rds_gbc_get)(void);  //good block counter
+    fm_u16(*rds_bbc_get)(void);  //bad block counter
+    fm_u8(*rds_bbr_get)(void);   //bad block ratio
+    fm_s32(*rds_bc_reset)(void);  //reset block counter
+    fm_u32(*rds_bci_get)(void);  //bler check interval
+    fm_s32(*rds_log_get)(struct rds_rx_t *dst, fm_s32 *dst_len);
+    fm_s32(*rds_gc_get)(struct rds_group_cnt_t *dst, rds_t *rdsp);
+    fm_s32(*rds_gc_reset)(rds_t *rdsp);
+    /*Tx*/
+    fm_s32(*rds_tx)(fm_u16 pi, fm_u16 *ps, fm_u16 *other_rds, fm_u8 other_rds_cnt);
+    fm_s32(*rds_tx_enable)(void);
+    fm_s32(*rds_tx_disable)(void);
+    fm_s32(*rdstx_support)(fm_s32 *sup);
+};
+
+struct fm_lowlevel_ops {
+    struct fm_callback cb;
+    struct fm_basic_interface bi;
+    struct fm_rds_interface ri;
+};
+
+#if (!defined(MT6620_FM)&&!defined(MT6628_FM))
+extern fm_s32 fm_low_ops_register(struct fm_lowlevel_ops *ops);
+extern fm_s32 fm_low_ops_unregister(struct fm_lowlevel_ops *ops);
+extern fm_s32 fm_rds_ops_register(struct fm_lowlevel_ops *ops);
+extern fm_s32 fm_rds_ops_unregister(struct fm_lowlevel_ops *ops);
+#endif
+#ifdef MT6620_FM
+extern fm_s32 MT6620fm_low_ops_register(struct fm_lowlevel_ops *ops);
+extern fm_s32 MT6620fm_low_ops_unregister(struct fm_lowlevel_ops *ops);
+extern fm_s32 MT6620fm_rds_ops_register(struct fm_lowlevel_ops *ops);
+extern fm_s32 MT6620fm_rds_ops_unregister(struct fm_lowlevel_ops *ops);
+#endif
+#ifdef MT6628_FM
+extern fm_s32 MT6628fm_low_ops_register(struct fm_lowlevel_ops *ops);
+extern fm_s32 MT6628fm_low_ops_unregister(struct fm_lowlevel_ops *ops);
+extern fm_s32 MT6628fm_rds_ops_register(struct fm_lowlevel_ops *ops);
+extern fm_s32 MT6628fm_rds_ops_unregister(struct fm_lowlevel_ops *ops);
+#endif
+/*
+ * fm_get_channel_space - get the spcace of gived channel
+ * @freq - value in 760~1080 or 7600~10800
+ *
+ * Return 0, if 760~1080; return 1, if 7600 ~ 10800, else err code < 0
+ */
+
+extern fm_s32 fm_get_channel_space(int freq);
+#endif //__FM_INTERFACE_H__
+
diff --git a/drivers/mtk_wcn_combo/drv_fm/inc/fm_ioctl.h b/drivers/mtk_wcn_combo/drv_fm/inc/fm_ioctl.h
new file mode 100755 (executable)
index 0000000..9fb403e
--- /dev/null
@@ -0,0 +1,80 @@
+#ifndef __FM_IOCTL_H__
+#define __FM_IOCTL_H__
+#include "fm_typedef.h"
+#include "fm_rds.h"
+#include "fm_main.h"
+
+#define FM_IOC_MAGIC        0xf5 // FIXME: any conflict?
+
+#define FM_IOCTL_POWERUP       _IOWR(FM_IOC_MAGIC, 0, struct fm_tune_parm*)
+#define FM_IOCTL_POWERDOWN     _IOWR(FM_IOC_MAGIC, 1, int32_t*)
+#define FM_IOCTL_TUNE          _IOWR(FM_IOC_MAGIC, 2, struct fm_tune_parm*)
+#define FM_IOCTL_SEEK          _IOWR(FM_IOC_MAGIC, 3, struct fm_seek_parm*)
+#define FM_IOCTL_SETVOL        _IOWR(FM_IOC_MAGIC, 4, uint32_t*)
+#define FM_IOCTL_GETVOL        _IOWR(FM_IOC_MAGIC, 5, uint32_t*)
+#define FM_IOCTL_MUTE          _IOWR(FM_IOC_MAGIC, 6, uint32_t*)
+#define FM_IOCTL_GETRSSI       _IOWR(FM_IOC_MAGIC, 7, int32_t*)
+#define FM_IOCTL_SCAN          _IOWR(FM_IOC_MAGIC, 8, struct fm_scan_parm*)
+#define FM_IOCTL_STOP_SCAN     _IO(FM_IOC_MAGIC,   9)
+#define FM_IOCTL_POWERUP_TX    _IOWR(FM_IOC_MAGIC, 20, struct fm_tune_parm*)
+#define FM_IOCTL_TUNE_TX       _IOWR(FM_IOC_MAGIC, 21, struct fm_tune_parm*)
+#define FM_IOCTL_RDS_TX        _IOWR(FM_IOC_MAGIC, 22, struct fm_rds_tx_parm*)
+
+//IOCTL and struct for test
+#define FM_IOCTL_GETCHIPID     _IOWR(FM_IOC_MAGIC, 10, uint16_t*)
+#define FM_IOCTL_EM_TEST       _IOWR(FM_IOC_MAGIC, 11, struct fm_em_parm*)
+#define FM_IOCTL_RW_REG        _IOWR(FM_IOC_MAGIC, 12, struct fm_ctl_parm*)
+#define FM_IOCTL_GETMONOSTERO  _IOWR(FM_IOC_MAGIC, 13, uint16_t*)
+#define FM_IOCTL_GETCURPAMD    _IOWR(FM_IOC_MAGIC, 14, uint16_t*)
+#define FM_IOCTL_GETGOODBCNT   _IOWR(FM_IOC_MAGIC, 15, uint16_t*)
+#define FM_IOCTL_GETBADBNT     _IOWR(FM_IOC_MAGIC, 16, uint16_t*)
+#define FM_IOCTL_GETBLERRATIO  _IOWR(FM_IOC_MAGIC, 17, uint16_t*)
+
+//IOCTL for RDS 
+#define FM_IOCTL_RDS_ONOFF     _IOWR(FM_IOC_MAGIC, 18, uint16_t*)
+#define FM_IOCTL_RDS_SUPPORT   _IOWR(FM_IOC_MAGIC, 19, int32_t*)
+
+#define FM_IOCTL_RDS_SIM_DATA  _IOWR(FM_IOC_MAGIC, 23, uint32_t*)
+#define FM_IOCTL_IS_FM_POWERED_UP  _IOWR(FM_IOC_MAGIC, 24, uint32_t*)
+
+//IOCTL for FM Tx
+#define FM_IOCTL_TX_SUPPORT    _IOWR(FM_IOC_MAGIC, 25, int32_t*)
+#define FM_IOCTL_RDSTX_SUPPORT _IOWR(FM_IOC_MAGIC, 26, int32_t*)
+#define FM_IOCTL_RDSTX_ENABLE  _IOWR(FM_IOC_MAGIC, 27, int32_t*)
+#define FM_IOCTL_TX_SCAN       _IOWR(FM_IOC_MAGIC, 28, struct fm_tx_scan_parm*)
+
+//IOCTL for FM over BT
+#define FM_IOCTL_OVER_BT_ENABLE  _IOWR(FM_IOC_MAGIC, 29, int32_t*)
+
+//IOCTL for FM ANTENNA SWITCH
+#define FM_IOCTL_ANA_SWITCH     _IOWR(FM_IOC_MAGIC, 30, int32_t*)
+#define FM_IOCTL_GETCAPARRAY   _IOWR(FM_IOC_MAGIC, 31, int32_t*)
+
+//IOCTL for FM compensation by GPS RTC
+#define FM_IOCTL_GPS_RTC_DRIFT  _IOWR(FM_IOC_MAGIC, 32, struct fm_gps_rtc_info*)
+
+//IOCTL for FM I2S Setting
+#define FM_IOCTL_I2S_SETTING  _IOWR(FM_IOC_MAGIC, 33, struct fm_i2s_setting*)
+
+#define FM_IOCTL_RDS_GROUPCNT   _IOWR(FM_IOC_MAGIC, 34, struct rds_group_cnt_req_t*)
+#define FM_IOCTL_RDS_GET_LOG    _IOWR(FM_IOC_MAGIC, 35, struct rds_raw_t*)
+
+#define FM_IOCTL_SCAN_GETRSSI   _IOWR(FM_IOC_MAGIC, 36, struct fm_rssi_req*)
+#define FM_IOCTL_SETMONOSTERO   _IOWR(FM_IOC_MAGIC, 37, int32_t)
+
+#define FM_IOCTL_RDS_BC_RST     _IOWR(FM_IOC_MAGIC, 38, int32_t*)
+#define FM_IOCTL_CQI_GET     _IOWR(FM_IOC_MAGIC, 39, struct fm_cqi_req*)
+#define FM_IOCTL_GET_HW_INFO    _IOWR(FM_IOC_MAGIC, 40, struct fm_hw_info*)
+#define FM_IOCTL_GET_I2S_INFO   _IOWR(FM_IOC_MAGIC, 41, struct fm_i2s_info*)
+#define FM_IOCTL_IS_DESE_CHAN   _IOWR(FM_IOC_MAGIC, 42, int32_t*)
+
+#define FM_IOCTL_SCAN_NEW       _IOWR(FM_IOC_MAGIC, 60, struct fm_scan_t*)
+#define FM_IOCTL_SEEK_NEW       _IOWR(FM_IOC_MAGIC, 61, struct fm_seek_t*)
+#define FM_IOCTL_TUNE_NEW       _IOWR(FM_IOC_MAGIC, 62, struct fm_tune_t*)
+#define FM_IOCTL_SOFT_MUTE_TUNE _IOWR(FM_IOC_MAGIC, 63, struct fm_softmute_tune_t*)/*for soft mute tune*/
+#define FM_IOCTL_DESENSE_CHECK   _IOWR(FM_IOC_MAGIC, 64, fm_desense_check_t*)
+
+#define FM_IOCTL_DUMP_REG   _IO(FM_IOC_MAGIC, 0xFF)
+
+#endif //__FM_IOCTL_H__
+
diff --git a/drivers/mtk_wcn_combo/drv_fm/inc/fm_link.h b/drivers/mtk_wcn_combo/drv_fm/inc/fm_link.h
new file mode 100755 (executable)
index 0000000..696a1dd
--- /dev/null
@@ -0,0 +1,218 @@
+#ifndef __FM_LINK_H__
+#define __FM_LINK_H__
+
+#include "fm_typedef.h"
+#include "fm_rds.h"
+
+typedef enum {
+    FM_TASK_RX_PARSER_PKT_TYPE = 0,
+    FM_TASK_RX_PARSER_OPCODE,
+    FM_TASK_RX_PARSER_PKT_LEN_1,
+    FM_TASK_RX_PARSER_PKT_LEN_2,
+    FM_TASK_RX_PARSER_PKT_PAYLOAD,
+    FM_TASK_RX_PARSER_BUFFER_CONGESTION
+} fm_task_parser_state;
+
+enum {
+    FM_TASK_COMMAND_PKT_TYPE = 0x01,
+    FM_TASK_EVENT_PKT_TYPE = 0x04
+};
+
+enum {
+    FM_STP_TEST_OPCODE      = 0x00,
+    FSPI_ENABLE_OPCODE      = 0x01,
+    FSPI_MUX_SEL_OPCODE     = 0x02,
+    FSPI_READ_OPCODE        = 0x03,
+    FSPI_WRITE_OPCODE       = 0x04,
+    FI2C_READ_OPCODE        = 0x05,
+    FI2C_WRITE_OPCODE       = 0x06,
+    FM_ENABLE_OPCODE        = 0x07,
+    FM_RESET_OPCODE         = 0x08,
+    FM_TUNE_OPCODE          = 0x09,
+    FM_SEEK_OPCODE          = 0x0a,
+    FM_SCAN_OPCODE          = 0x0b,
+    RDS_RX_ENABLE_OPCODE    = 0x0c,
+    RDS_RX_DATA_OPCODE      = 0x0d,
+    FM_RAMPDOWN_OPCODE      = 0x0e,
+    FM_MCUCLK_SEL_OPCODE    = 0x0f,
+    FM_MODEMCLK_SEL_OPCODE  = 0x10,
+    RDS_TX_OPCODE           = 0x11,
+    FM_PATCH_DOWNLOAD_OPCODE = 0x12,
+    FM_COEFF_DOWNLOAD_OPCODE = 0x13,
+    FM_HWCOEFF_DOWNLOAD_OPCODE = 0x14,
+    FM_ROM_DOWNLOAD_OPCODE = 0x15,
+    FM_SOFT_MUTE_TUNE_OPCODE = 0x17,
+};
+
+enum {
+    FLAG_TEST = (1 << FM_STP_TEST_OPCODE),
+    FLAG_FSPI_EN = (1 << FSPI_ENABLE_OPCODE),
+    FLAG_FSPI_MUXSEL = (1 << FSPI_MUX_SEL_OPCODE),
+    FLAG_FSPI_RD = (1 << FSPI_READ_OPCODE),
+    FLAG_FSPI_WR = (1 << FSPI_WRITE_OPCODE),
+    FLAG_I2C_RD = (1 << FI2C_READ_OPCODE),
+    FLAG_I2C_WR = (1 << FI2C_WRITE_OPCODE),
+    FLAG_EN = (1 << FM_ENABLE_OPCODE),
+    FLAG_RST = (1 << FM_RESET_OPCODE),
+    FLAG_TUNE = (1 << FM_TUNE_OPCODE),
+    FLAG_SEEK = (1 << FM_SEEK_OPCODE),
+    FLAG_SCAN = (1 << FM_SCAN_OPCODE),
+    FLAG_RDS_RX_EN = (1 << RDS_RX_ENABLE_OPCODE),
+    FLAG_RDS_DATA = (1 << RDS_RX_DATA_OPCODE),
+    FLAG_RAMPDOWN = (1 << FM_RAMPDOWN_OPCODE),
+    FLAG_MCUCLK = (1 << FM_MCUCLK_SEL_OPCODE),
+    FLAG_MODEMCLK = (1 << FM_MODEMCLK_SEL_OPCODE),
+    FLAG_RDS_TX = (1 << RDS_TX_OPCODE),
+    FLAG_PATCH = (1 << FM_PATCH_DOWNLOAD_OPCODE),
+    FLAG_COEFF = (1 << FM_COEFF_DOWNLOAD_OPCODE),
+    FLAG_HWCOEFF = (1 << FM_HWCOEFF_DOWNLOAD_OPCODE),
+    FLAG_ROM = (1 << FM_ROM_DOWNLOAD_OPCODE),
+    FLAG_SM_TUNE = (1 << FM_SOFT_MUTE_TUNE_OPCODE), // 23
+    FLAG_CQI_DONE = (1 << 27),
+    FLAG_TUNE_DONE = (1 << 28),
+    FLAG_SEEK_DONE = (1 << 29),
+    FLAG_SCAN_DONE = (1 << 30),
+    FLAG_TERMINATE = (1 << 31)
+};
+
+#define FM_SCANTBL_SIZE  16
+#define FM_CQI_BUF_SIZE  96
+struct fm_res_ctx {
+    fm_u16 fspi_rd;
+    fm_u16 seek_result;
+    fm_u16 scan_result[FM_SCANTBL_SIZE];
+    fm_s8 cqi[FM_CQI_BUF_SIZE];
+    struct rds_rx_t rds_rx_result;
+};
+
+#define FM_TRACE_ENABLE
+
+#define FM_TRACE_FIFO_SIZE 200
+#define FM_TRACE_PKT_SIZE 60
+struct fm_trace_t {
+    fm_s32 type;
+    fm_s32 opcode;
+    fm_s32 len;
+    fm_u8 pkt[FM_TRACE_PKT_SIZE]; // full packet
+    unsigned long time;
+    fm_s32 tid;
+};
+
+struct fm_trace_fifo_t {
+    fm_s8 name[20+1];
+    struct fm_trace_t trace[FM_TRACE_FIFO_SIZE];
+    fm_u32 size;
+    fm_u32 in;
+    fm_u32 out;
+    fm_u32 len;
+    fm_s32 (*trace_in)(struct fm_trace_fifo_t *thiz, struct fm_trace_t *new_tra);
+    fm_s32 (*trace_out)(struct fm_trace_fifo_t *thiz, struct fm_trace_t *dst_tra);
+    fm_bool (*is_full)(struct fm_trace_fifo_t *thiz);
+    fm_bool (*is_empty)(struct fm_trace_fifo_t *thiz);
+};
+
+#define FM_TRACE_IN(fifop, tracep)  \
+({                                    \
+    fm_s32 __ret = (fm_s32)0;              \
+    if(fifop && (fifop)->trace_in){          \
+        __ret = (fifop)->trace_in(fifop, tracep);   \
+    }                               \
+    __ret;                          \
+})
+
+#define FM_TRACE_OUT(fifop, tracep)  \
+({                                    \
+    fm_s32 __ret = (fm_s32)0;              \
+    if(fifop && (fifop)->trace_out){          \
+        __ret = (fifop)->trace_out(fifop, tracep);   \
+    }                               \
+    __ret;                          \
+})
+
+#define FM_TRACE_FULL(fifop)  \
+({                                    \
+    fm_bool __ret = (fm_bool)fm_false;      \
+    if(fifop && (fifop)->is_full){          \
+        __ret = (fifop)->is_full(fifop);   \
+    }                               \
+    __ret;                          \
+})
+
+#define FM_TRACE_EMPTY(fifop)  \
+({                                    \
+    fm_bool __ret = (fm_bool)fm_false;      \
+    if(fifop && (fifop)->is_empty){          \
+        __ret = (fifop)->is_empty(fifop);   \
+    }                               \
+    __ret;                          \
+})
+
+#if (defined(MT6620_FM)||defined(MT6628_FM))
+#include "fm_utils.h"
+
+#define RX_BUF_SIZE 128
+#define TX_BUF_SIZE 1024
+
+#define SW_RETRY_CNT            (1)
+#define SW_RETRY_CNT_MAX        (5)
+#define SW_WAIT_TIMEOUT_MAX     (100)
+// FM operation timeout define for error handle
+#define TEST_TIMEOUT            (3)
+#define FSPI_EN_TIMEOUT         (3)
+#define FSPI_MUXSEL_TIMEOUT     (3)
+#define FSPI_RD_TIMEOUT         (3)
+#define FSPI_WR_TIMEOUT         (3)
+#define I2C_RD_TIMEOUT          (3)
+#define I2C_WR_TIMEOUT          (3)
+#define EN_TIMEOUT              (3)
+#define RST_TIMEOUT             (3)
+#define TUNE_TIMEOUT            (3)
+#define SM_TUNE_TIMEOUT         (6)
+#define SEEK_TIMEOUT            (15)
+#define SCAN_TIMEOUT            (15) //usualy scan will cost 10 seconds 
+#define RDS_RX_EN_TIMEOUT       (3)
+#define RDS_DATA_TIMEOUT        (100)
+#define RAMPDOWN_TIMEOUT        (3)
+#define MCUCLK_TIMEOUT          (3)
+#define MODEMCLK_TIMEOUT        (3)
+#define RDS_TX_TIMEOUT          (3)
+#define PATCH_TIMEOUT           (3)
+#define COEFF_TIMEOUT           (3)
+#define HWCOEFF_TIMEOUT         (3)
+#define ROM_TIMEOUT             (3)
+
+struct fm_link_event {
+       struct fm_flag_event *ln_event;
+       struct fm_res_ctx result; // seek/scan/read/RDS
+};
+#endif
+
+/*
+ * FM data and ctrl link APIs: platform related and bus related
+ */
+extern fm_s32 fm_link_setup(void* data);
+
+extern fm_s32 fm_link_release(void);
+
+extern fm_s32 fm_cmd_tx(fm_u8* buf, fm_u16 len, fm_s32 mask, fm_s32 cnt, fm_s32 timeout, fm_s32(*callback)(struct fm_res_ctx* result));
+
+extern fm_s32 fm_event_parser(fm_s32(*rds_parser)(struct rds_rx_t*, fm_s32));
+
+extern fm_s32 fm_ctrl_rx(fm_u8 addr, fm_u16 *val);
+
+extern fm_s32 fm_ctrl_tx(fm_u8 addr, fm_u16 val);
+
+extern fm_s32 fm_force_active_event(fm_u32 mask);
+
+extern fm_bool fm_wait_stc_done(fm_u32 sec);
+
+extern struct fm_trace_fifo_t* fm_trace_fifo_create(const fm_s8 *name);
+
+extern fm_s32 fm_trace_fifo_release(struct fm_trace_fifo_t *fifo);
+
+extern fm_s32 fm_print_cmd_fifo(void);
+
+extern fm_s32 fm_print_evt_fifo(void);
+
+#endif //__FM_LINK_H__
+
diff --git a/drivers/mtk_wcn_combo/drv_fm/inc/fm_main.h b/drivers/mtk_wcn_combo/drv_fm/inc/fm_main.h
new file mode 100755 (executable)
index 0000000..12f5a08
--- /dev/null
@@ -0,0 +1,384 @@
+#ifndef __FM_MAIN_H__
+#define __FM_MAIN_H__
+#include "fm_typedef.h"
+#include "fm_dbg.h"
+#include "fm_err.h"
+#include "fm_rds.h"
+#include "fm_eint.h"
+#include "fm_link.h"
+#include "fm_interface.h"
+#include "fm_stdlib.h"
+#include "fm_private.h"
+
+#define FM_NAME             "fm"
+#define FM_DEVICE_NAME      "/dev/fm"
+
+#define FM_VOL_MAX           0x2B      // 43 volume(0-15)
+#define FM_TIMER_TIMEOUT_DEFAULT 1000
+#define FM_TIMER_TIMEOUT_MIN 1000
+#define FM_TIMER_TIMEOUT_MAX 1000000
+//FM Tx
+#define FM_TX_PWR_LEVEL_MAX  120         //FM transmitter power level, rang: 85db~120db, default 120db
+
+#define FM_TX_PWR_CTRL_INVAL_DEFAULT 10
+#define FM_TX_PWR_CTRL_INVAL_MIN 5
+#define FM_TX_PWR_CTRL_INVAL_MAX 10000
+
+#define FM_TX_VCO_OFF_DEFAULT 5
+#define FM_TX_VCO_OFF_MIN 1
+#define FM_TX_VCO_OFF_MAX 10000
+
+#define FM_TX_VCO_ON_DEFAULT 100
+#define FM_TX_VCO_ON_MIN 10
+#define FM_TX_VCO_ON_MAX 10000
+
+#define FM_GPS_RTC_AGE_TH       2
+#define FM_GPS_RTC_DRIFT_TH     0
+#define FM_GPS_RTC_TIME_DIFF_TH 10
+#define FM_GPS_RTC_RETRY_CNT    1
+#define FM_GPS_RTC_DRIFT_MAX 5000
+enum{
+    FM_GPS_RTC_INFO_OLD = 0,
+    FM_GPS_RTC_INFO_NEW = 1,
+    FM_GPS_RTC_INFO_MAX
+};
+
+typedef enum
+{
+       FM_OVER_BT_DISABLE = 0,
+       FM_OVER_BT_ENABLE
+}fm_over_bt_enable_state;
+
+#define FM_RDS_ENABLE          0x01 // 1: enable RDS, 0:disable RDS
+#define FM_RDS_DATA_READY   (1 << 0)
+
+// errno
+#define FM_SUCCESS      0
+#define FM_FAILED       1
+#define FM_EPARM        2
+#define FM_BADSTATUS    3
+#define FM_TUNE_FAILED  4
+#define FM_SEEK_FAILED  5
+#define FM_BUSY         6
+#define FM_SCAN_FAILED  7
+
+struct fm_tune_parm {
+    fm_u8 err;
+    fm_u8 band;
+    fm_u8 space;
+    fm_u8 hilo;
+    fm_u16 freq; // IN/OUT parameter
+};
+
+struct fm_seek_parm {
+    fm_u8 err;
+    fm_u8 band;
+    fm_u8 space;
+    fm_u8 hilo;
+    fm_u8 seekdir;
+    fm_u8 seekth;
+    fm_u16 freq; // IN/OUT parameter
+};
+
+#ifdef MTK_FM_50KHZ_SUPPORT
+struct fm_scan_parm {
+    fm_u8  err;
+    fm_u8  band;
+    fm_u8  space;
+    fm_u8  hilo;
+    fm_u16 freq; // OUT parameter
+    fm_u16 ScanTBL[26]; //need no less than the chip
+    fm_u16 ScanTBLSize; //IN/OUT parameter
+};
+#else
+struct fm_scan_parm {
+    fm_u8  err;
+    fm_u8  band;
+    fm_u8  space;
+    fm_u8  hilo;
+    fm_u16 freq; // OUT parameter
+    fm_u16 ScanTBL[16]; //need no less than the chip
+    fm_u16 ScanTBLSize; //IN/OUT parameter
+};
+#endif
+
+struct fm_cqi {
+    fm_s32 ch;
+    fm_s32 rssi;
+    fm_s32 reserve;
+};
+
+struct fm_cqi_req {
+    fm_u16 ch_num;
+    fm_s32 buf_size;
+    fm_s8 *cqi_buf;
+};
+
+struct fm_ch_rssi {
+    fm_u16 freq;
+    fm_s32 rssi;
+};
+
+enum fm_scan_cmd_t {
+    FM_SCAN_CMD_INIT = 0,
+    FM_SCAN_CMD_START,
+    FM_SCAN_CMD_GET_NUM,
+    FM_SCAN_CMD_GET_CH,
+    FM_SCAN_CMD_GET_RSSI,
+    FM_SCAN_CMD_GET_CH_RSSI,
+    FM_SCAN_CMD_MAX
+};
+
+struct fm_scan_t {
+    enum fm_scan_cmd_t cmd;    
+    fm_s32 ret;    // 0, success; else error code
+    fm_u16 lower;             // lower band, Eg, 7600 -> 76.0Mhz
+    fm_u16 upper;             // upper band, Eg, 10800 -> 108.0Mhz
+    fm_s32 space;                  // 5: 50KHz, 10: 100Khz, 20: 200Khz
+    fm_s32 num;                    // valid channel number 
+    void *priv;
+    fm_s32 sr_size;                // scan result buffer size in bytes
+    union {
+        fm_u16 *ch_buf;       // channel buffer
+        fm_s32 *rssi_buf;          // rssi buffer
+        struct fm_ch_rssi *ch_rssi_buf;  //channel and RSSI buffer 
+    } sr;    
+};
+
+struct fm_seek_t {  
+    fm_s32 ret;                    // 0, success; else error code
+    fm_u16 freq;
+    fm_u16 lower;             // lower band, Eg, 7600 -> 76.0Mhz
+    fm_u16 upper;             // upper band, Eg, 10800 -> 108.0Mhz
+    fm_s32 space;                  // 5: 50KHz, 10: 100Khz, 20: 200Khz
+    fm_s32 dir;                    // 0: up; 1: down
+    fm_s32 th;                     // seek threshold in dbm(Eg, -95dbm)
+    void *priv;
+};
+
+struct fm_tune_t {  
+    fm_s32 ret;                    // 0, success; else error code
+    fm_u16 freq;
+    fm_u16 lower;             // lower band, Eg, 7600 -> 76.0Mhz
+    fm_u16 upper;             // upper band, Eg, 10800 -> 108.0Mhz
+    fm_s32 space;                  // 5: 50KHz, 10: 100Khz, 20: 200Khz
+    void *priv;
+};
+
+
+#ifdef MTK_FM_50KHZ_SUPPORT
+struct fm_rssi_req {
+    fm_u16 num;
+    fm_u16 read_cnt;
+    struct fm_ch_rssi cr[26*16];
+};
+#else
+struct fm_rssi_req {
+    fm_u16 num;
+    fm_u16 read_cnt;
+    struct fm_ch_rssi cr[16*16];
+};
+#endif
+
+struct fm_rds_tx_parm {
+    fm_u8 err;
+    fm_u16 pi;
+    fm_u16 ps[12]; // 4 ps
+    fm_u16 other_rds[87];  // 0~29 other groups
+    fm_u8 other_rds_cnt; // # of other group
+};
+
+typedef struct fm_rds_tx_req {
+    unsigned char pty;         // 0~31 integer
+    unsigned char rds_rbds;    // 0:RDS, 1:RBDS
+    unsigned char dyn_pty;     // 0:static, 1:dynamic
+    unsigned short pi_code;    // 2-byte hex
+    unsigned char ps_buf[8];     // hex buf of PS
+    unsigned char ps_len;      // length of PS, must be 0 / 8"
+    unsigned char af;          // 0~204, 0:not used, 1~204:(87.5+0.1*af)MHz
+    unsigned char ah;          // Artificial head, 0:no, 1:yes
+    unsigned char stereo;      // 0:mono, 1:stereo
+    unsigned char compress;    // Audio compress, 0:no, 1:yes
+    unsigned char tp;          // traffic program, 0:no, 1:yes
+    unsigned char ta;          // traffic announcement, 0:no, 1:yes
+    unsigned char speech;      // 0:music, 1:speech
+} fm_rds_tx_req;
+
+#define TX_SCAN_MAX 10
+#define TX_SCAN_MIN 1
+
+struct fm_tx_scan_parm {
+    fm_u8  err;
+    fm_u8  band;       //87.6~108MHz
+    fm_u8  space;
+    fm_u8  hilo;
+    fm_u16 freq;       // start freq, if less than band min freq, then will use band min freq
+    fm_u8 scandir;
+    fm_u16 ScanTBL[TX_SCAN_MAX];       //need no less than the chip
+    fm_u16 ScanTBLSize; //IN: desired size, OUT: scan result size
+};
+
+struct fm_gps_rtc_info {
+    fm_s32             err;            //error number, 0: success, other: err code
+    fm_s32             retryCnt;       //GPS mnl can decide retry times
+    fm_s32             ageThd;         //GPS 3D fix time diff threshold
+    fm_s32             driftThd;       //GPS RTC drift threshold
+    struct timeval  tvThd;          //time value diff threshold
+    fm_s32             age;            //GPS 3D fix time diff
+    fm_s32             drift;          //GPS RTC drift
+    union {
+        unsigned long stamp;        //time stamp in jiffies
+        struct timeval  tv;         //time stamp value in RTC
+    };
+    fm_s32             flag;           //rw flag
+};
+
+typedef enum {
+    FM_I2S_ON = 0,
+    FM_I2S_OFF
+} fm_i2s_state;
+
+typedef enum {
+    FM_I2S_MASTER = 0,
+    FM_I2S_SLAVE
+} fm_i2s_mode;
+
+typedef enum {
+    FM_I2S_32K = 0,
+    FM_I2S_44K,
+    FM_I2S_48K
+} fm_i2s_sample;
+
+struct fm_i2s_setting {
+    fm_s32 onoff;
+    fm_s32 mode;
+    fm_s32 sample;
+};
+typedef struct
+{
+       fm_s32 freq;
+       fm_s32 rssi;
+}fm_desense_check_t;
+
+typedef enum {
+    FM_RX = 0,
+    FM_TX = 1
+} FM_PWR_T;
+
+struct fm_ctl_parm {
+       fm_u8 err;
+       fm_u8 addr;
+       fm_u16 val;
+       fm_u16 rw_flag;//0:write, 1:read
+};
+struct fm_em_parm {
+       fm_u16 group_idx;
+       fm_u16 item_idx;
+       fm_u32 item_value;
+};
+
+enum {
+    FM_SUBSYS_RST_OFF,
+    FM_SUBSYS_RST_START,
+    FM_SUBSYS_RST_END,
+    FM_SUBSYS_RST_MAX
+};
+enum{
+    FM_TX_PWR_CTRL_DISABLE,
+    FM_TX_PWR_CTRL_ENABLE,
+    FM_TX_PWR_CTRL_MAX
+};
+
+enum{
+    FM_TX_RTC_CTRL_DISABLE,
+    FM_TX_RTC_CTRL_ENABLE,
+    FM_TX_RTC_CTRL_MAX
+};
+
+enum{
+    FM_TX_DESENSE_DISABLE,
+    FM_TX_DESENSE_ENABLE,
+    FM_TX_DESENSE_MAX
+};
+
+struct fm_softmute_tune_t 
+{  
+       fm_s32 rssi;              // RSSI of current channel
+       fm_u16 freq;                            //current frequency
+       fm_bool valid;                              //current channel is valid(true) or not(false)
+};
+
+//init and deinit APIs
+extern fm_s32 fm_env_setup(void);
+extern fm_s32 fm_env_destroy(void);
+extern struct fm* fm_dev_init(fm_u32 arg);
+extern fm_s32 fm_dev_destroy(struct fm *fm);
+
+
+//fm main basic APIs
+extern enum fm_pwr_state fm_pwr_state_get(struct fm *fmp);
+extern enum fm_pwr_state fm_pwr_state_set(struct fm *fmp, enum fm_pwr_state sta);
+extern fm_s32 fm_open(struct fm *fmp);
+extern fm_s32 fm_close(struct fm *fmp);
+extern fm_s32 fm_rds_read(struct fm *fmp, fm_s8 *dst, fm_s32 len);
+extern fm_s32 fm_powerup(struct fm *fm, struct fm_tune_parm *parm);
+extern fm_s32 fm_powerdown(struct fm *fm);
+extern fm_s32 fm_seek(struct fm *fm, struct fm_seek_parm *parm);
+extern fm_s32 fm_scan(struct fm *fm, struct fm_scan_parm *parm);
+extern fm_s32 fm_cqi_get(struct fm *fm, fm_s32 ch_num, fm_s8 *buf, fm_s32 buf_size);
+extern fm_s32 fm_get_hw_info(struct fm *pfm, struct fm_hw_info *req);
+extern fm_s32 fm_hwscan_stop(struct fm *fm);
+extern fm_s32 fm_ana_switch(struct fm *fm, fm_s32 antenna);
+extern fm_s32 fm_setvol(struct fm *fm, fm_u32 vol);
+extern fm_s32 fm_getvol(struct fm *fm, fm_u32 *vol);
+extern fm_s32 fm_mute(struct fm *fm, fm_u32 bmute);
+extern fm_s32 fm_getrssi(struct fm *fm, fm_s32 *rssi);
+extern fm_s32 fm_reg_read(struct fm *fm, fm_u8 addr, fm_u16 *val);
+extern fm_s32 fm_reg_write(struct fm *fm, fm_u8 addr, fm_u16 val);
+extern fm_s32 fm_chipid_get(struct fm *fm, fm_u16 *chipid);
+extern fm_s32 fm_monostereo_get(struct fm *fm, fm_u16 *ms);
+extern fm_s32 fm_monostereo_set(struct fm *fm, fm_s32 ms);
+extern fm_s32 fm_pamd_get(struct fm *fm, fm_u16 *pamd);
+extern fm_s32 fm_caparray_get(struct fm *fm, fm_s32 *ca);
+extern fm_s32 fm_em_test(struct fm *fm, fm_u16 group, fm_u16 item, fm_u32 val);
+extern fm_s32 fm_rds_onoff(struct fm *fm, fm_u16 rdson_off);
+extern fm_s32 fm_rds_good_bc_get(struct fm *fm, fm_u16 *gbc);
+extern fm_s32 fm_rds_bad_bc_get(struct fm *fm, fm_u16 *bbc);
+extern fm_s32 fm_rds_bler_ratio_get(struct fm *fm, fm_u16 *bbr);
+extern fm_s32 fm_rds_group_cnt_get(struct fm *fm, struct rds_group_cnt_t *dst);
+extern fm_s32 fm_rds_group_cnt_reset(struct fm *fm);
+extern fm_s32 fm_rds_log_get(struct fm *fm, struct rds_rx_t *dst, fm_s32 *dst_len);
+extern fm_s32 fm_rds_block_cnt_reset(struct fm *fm);
+extern fm_s32 fm_i2s_set(struct fm *fm, fm_s32 onoff, fm_s32 mode, fm_s32 sample);
+extern fm_s32 fm_get_i2s_info(struct fm *pfm, struct fm_i2s_info *req);
+extern fm_s32 fm_tune(struct fm *fm, struct fm_tune_parm *parm);
+extern fm_s32 fm_is_dese_chan(struct fm *pfm, fm_u16 freq);
+extern fm_s32 fm_desense_check(struct fm *pfm, fm_u16 freq,fm_s32 rssi);
+extern fm_s32 fm_sys_state_get(struct fm *fmp);
+extern fm_s32 fm_sys_state_set(struct fm *fmp, fm_s32 sta);
+extern fm_s32 fm_subsys_reset(struct fm *fm);
+
+extern fm_s32 fm_scan_new(struct fm *fm, struct fm_scan_t *parm);
+extern fm_s32 fm_seek_new(struct fm *fm, struct fm_seek_t *parm);
+extern fm_s32 fm_tune_new(struct fm *fm, struct fm_tune_t *parm);
+
+extern fm_s32 fm_cust_config_setup(fm_s8 * filename);
+extern fm_s32 fm_cqi_log(void);
+extern fm_s32 fm_soft_mute_tune(struct fm *fm, struct fm_softmute_tune_t *parm);
+extern fm_s32 fm_dump_reg(void);
+extern fm_s32 fm_get_gps_rtc_info(struct fm_gps_rtc_info *src);
+extern fm_s32 fm_over_bt(struct fm *fm, fm_s32 flag);
+
+/*tx function*/
+extern fm_s32 fm_tx_support(struct fm *fm, fm_s32 *support);
+
+extern fm_s32 fm_powerup_tx(struct fm *fm, struct fm_tune_parm *parm);
+extern fm_s32 fm_tune_tx(struct fm *fm, struct fm_tune_parm *parm);
+extern fm_s32 fm_powerdowntx(struct fm *fm);
+extern fm_s32 fm_rds_tx(struct fm *fm, struct fm_rds_tx_parm *parm);
+extern fm_s32 fm_rdstx_support(struct fm *fm, fm_s32 *support);
+extern fm_s32 fm_rdstx_enable(struct fm *fm, fm_s32 *support);
+extern fm_s32 fm_tx_scan(struct fm *fm, struct fm_tx_scan_parm *parm);
+
+#endif //__FM_MAIN_H__
+
diff --git a/drivers/mtk_wcn_combo/drv_fm/inc/fm_patch.h b/drivers/mtk_wcn_combo/drv_fm/inc/fm_patch.h
new file mode 100755 (executable)
index 0000000..bd56300
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef __FM_PATCH_H__
+#define __FM_PATCH_H__
+
+enum {
+    FM_ROM_V1 = 0,
+    FM_ROM_V2 = 1,
+    FM_ROM_V3 = 2,
+    FM_ROM_V4 = 3,
+    FM_ROM_V5 = 4,
+    FM_ROM_MAX
+};
+
+struct fm_patch_tbl {
+    fm_s32 idx;
+    fm_s8 *patch;
+    fm_s8 *coeff;
+    fm_s8 *rom;
+    fm_s8 *hwcoeff;
+};
+
+extern fm_s32 fm_file_exist(const fm_s8 *filename);
+
+extern fm_s32 fm_file_read(const fm_s8 *filename, fm_u8* dst, fm_s32 len, fm_s32 position);
+
+extern fm_s32 fm_file_write(const fm_s8 *filename, fm_u8* dst, fm_s32 len, fm_s32 *ppos);
+
+
+#endif //__FM_PATCH_H__
+
diff --git a/drivers/mtk_wcn_combo/drv_fm/inc/fm_rds.h b/drivers/mtk_wcn_combo/drv_fm/inc/fm_rds.h
new file mode 100755 (executable)
index 0000000..9d0a929
--- /dev/null
@@ -0,0 +1,219 @@
+#ifndef __FM_RDS_H__
+#define __FM_RDS_H__
+#include "fm_typedef.h"
+
+//FM_RDS_DATA_CRC_FFOST
+#define FM_RDS_GDBK_IND_A       (0x08)
+#define FM_RDS_GDBK_IND_B       (0x04)
+#define FM_RDS_GDBK_IND_C       (0x02)
+#define FM_RDS_GDBK_IND_D       (0x01)
+#define FM_RDS_DCO_FIFO_OFST (0x01E0)
+#define        FM_RDS_READ_DELAY        (0x80)
+
+#define RDS_RX_BLOCK_PER_GROUP (4)
+#define RDS_RX_GROUP_SIZE (2*RDS_RX_BLOCK_PER_GROUP)
+#define MAX_RDS_RX_GROUP_CNT (12)
+#define RDS_RT_MULTI_REV_TH 100
+
+typedef struct rds_packet_t {
+    fm_u16 blkA;
+    fm_u16 blkB;
+    fm_u16 blkC;
+    fm_u16 blkD;
+    fm_u16 cbc; //correct bit cnt
+    fm_u16 crc; //crc checksum
+} rds_packet_t;
+
+typedef struct rds_rx_t {
+    fm_u16 sin;
+    fm_u16 cos;
+    rds_packet_t data[MAX_RDS_RX_GROUP_CNT];
+} rds_rx_t;
+
+typedef enum rds_ps_state_machine_t {
+    RDS_PS_START = 0,
+    RDS_PS_DECISION,
+    RDS_PS_GETLEN,
+    RDS_PS_DISPLAY,
+    RDS_PS_FINISH,
+    RDS_PS_MAX
+} rds_ps_state_machine_t;
+
+typedef enum rds_rt_state_machine_t {
+    RDS_RT_START = 0,
+    RDS_RT_DECISION,
+    RDS_RT_GETLEN,
+    RDS_RT_DISPLAY,
+    RDS_RT_FINISH,
+    RDS_RT_MAX
+} rds_rt_state_machine_t;
+
+
+enum {
+    RDS_GRP_VER_A = 0,  //group version A
+    RDS_GRP_VER_B
+};
+
+typedef enum rds_blk_t {
+    RDS_BLK_A = 0,
+    RDS_BLK_B,
+    RDS_BLK_C,
+    RDS_BLK_D,
+    RDS_BLK_MAX
+} rds_blk_t;
+
+//For RDS feature, these strcutures also be defined in "fm.h"
+typedef struct rds_flag_t {
+    fm_u8 TP;
+    fm_u8 TA;
+    fm_u8 Music;
+    fm_u8 Stereo;
+    fm_u8 Artificial_Head;
+    fm_u8 Compressed;
+    fm_u8 Dynamic_PTY;
+    fm_u8 Text_AB;
+    fm_u32 flag_status;
+} rds_flag_t;
+
+typedef struct rds_ct_t {
+    fm_u16 Month;
+    fm_u16 Day;
+    fm_u16 Year;
+    fm_u16 Hour;
+    fm_u16 Minute;
+    fm_u8 Local_Time_offset_signbit;
+    fm_u8 Local_Time_offset_half_hour;
+} rds_ct_t;
+
+typedef struct rds_af_t {
+    fm_s16 AF_Num;
+    fm_s16 AF[2][25];  //100KHz
+    fm_u8 Addr_Cnt;
+    fm_u8 isMethod_A;
+    fm_u8 isAFNum_Get;
+} rds_af_t;
+
+typedef struct rds_ps_t {
+    fm_u8 PS[4][8];
+    fm_u8 Addr_Cnt;
+} rds_ps_t;
+
+typedef struct rds_rt_t {
+    fm_u8 TextData[4][64];
+    fm_u8 GetLength;
+    fm_u8 isRTDisplay;
+    fm_u8 TextLength;
+    fm_u8 isTypeA;
+    fm_u8 BufCnt;
+    fm_u16 Addr_Cnt;
+} rds_rt_t;
+
+typedef struct rds_raw_t {
+    fm_s32 dirty; //indicate if the data changed or not
+    fm_s32 len; //the data len form chip
+    fm_u8 data[146];
+} rds_raw_t;
+
+typedef struct rds_group_cnt_t {
+    unsigned long total;
+    unsigned long groupA[16]; //RDS groupA counter
+    unsigned long groupB[16]; //RDS groupB counter
+} rds_group_cnt_t;
+
+typedef enum rds_group_cnt_op_t {
+    RDS_GROUP_CNT_READ = 0,
+    RDS_GROUP_CNT_WRITE,
+    RDS_GROUP_CNT_RESET,
+    RDS_GROUP_CNT_MAX
+} rds_group_cnt_op_t;
+
+typedef struct rds_group_cnt_req_t {
+    fm_s32 err;
+    enum rds_group_cnt_op_t op;
+    struct rds_group_cnt_t gc;
+} rds_group_cnt_req_t;
+
+typedef struct rds_t {
+    struct rds_ct_t CT;
+    struct rds_flag_t RDSFlag;
+    fm_u16 PI;
+    fm_u8 Switch_TP;
+    fm_u8 PTY;
+    struct rds_af_t AF_Data;
+    struct rds_af_t AFON_Data;
+    fm_u8 Radio_Page_Code;
+    fm_u16 Program_Item_Number_Code;
+    fm_u8 Extend_Country_Code;
+    fm_u16 Language_Code;
+    struct rds_ps_t PS_Data;
+    fm_u8 PS_ON[8];
+    struct rds_rt_t RT_Data;
+    fm_u16 event_status; //will use RDSFlag_Struct RDSFlag->flag_status to check which event, is that ok?
+    struct rds_group_cnt_t gc;
+} rds_t;
+
+
+//Need care the following definition.
+//valid Rds Flag for notify
+typedef enum rds_flag_status_t {
+    RDS_FLAG_IS_TP              = 0x0001, // Program is a traffic program
+    RDS_FLAG_IS_TA              = 0x0002, // Program currently broadcasts a traffic ann.
+    RDS_FLAG_IS_MUSIC           = 0x0004, // Program currently broadcasts music
+    RDS_FLAG_IS_STEREO          = 0x0008, // Program is transmitted in stereo
+    RDS_FLAG_IS_ARTIFICIAL_HEAD = 0x0010, // Program is an artificial head recording
+    RDS_FLAG_IS_COMPRESSED      = 0x0020, // Program content is compressed
+    RDS_FLAG_IS_DYNAMIC_PTY     = 0x0040, // Program type can change
+    RDS_FLAG_TEXT_AB            = 0x0080  // If this flag changes state, a new radio text                                       string begins
+} rds_flag_status_t;
+
+typedef enum rds_event_status_t {
+    RDS_EVENT_FLAGS          = 0x0001, // One of the RDS flags has changed state
+    RDS_EVENT_PI_CODE        = 0x0002, // The program identification code has changed
+    RDS_EVENT_PTY_CODE       = 0x0004, // The program type code has changed
+    RDS_EVENT_PROGRAMNAME    = 0x0008, // The program name has changed
+    RDS_EVENT_UTCDATETIME    = 0x0010, // A new UTC date/time is available
+    RDS_EVENT_LOCDATETIME    = 0x0020, // A new local date/time is available
+    RDS_EVENT_LAST_RADIOTEXT = 0x0040, // A radio text string was completed
+    RDS_EVENT_AF             = 0x0080, // Current Channel RF signal strength too weak, need do AF switch
+    RDS_EVENT_AF_LIST        = 0x0100, // An alternative frequency list is ready
+    RDS_EVENT_AFON_LIST      = 0x0200, // An alternative frequency list is ready
+    RDS_EVENT_TAON           = 0x0400,  // Other Network traffic announcement start
+    RDS_EVENT_TAON_OFF       = 0x0800, // Other Network traffic announcement finished.
+    RDS_EVENT_RDS            = 0x2000, // RDS Interrupt had arrived durint timer period
+    RDS_EVENT_NO_RDS         = 0x4000, // RDS Interrupt not arrived durint timer period
+    RDS_EVENT_RDS_TIMER      = 0x8000 // Timer for RDS Bler Check. ---- BLER  block error rate
+} rds_event_status_t;
+
+
+#define RDS_LOG_SIZE 2
+struct rds_log_t {
+    struct rds_rx_t rds_log[RDS_LOG_SIZE];
+    fm_s32 log_len[RDS_LOG_SIZE];
+    fm_u32 size;
+    fm_u32 in;
+    fm_u32 out;
+    fm_u32 len;
+    fm_s32(*log_in)(struct rds_log_t *thiz, struct rds_rx_t *new_log, fm_s32 new_len);
+    fm_s32(*log_out)(struct rds_log_t *thiz, struct rds_rx_t *dst, fm_s32 *dst_len);
+};
+
+extern fm_s32 rds_parser(rds_t *rds_dst, struct rds_rx_t *rds_raw, fm_s32 rds_size, fm_u16(*getfreq)(void));
+extern fm_s32 rds_grp_counter_get(struct rds_group_cnt_t *dst, struct rds_group_cnt_t *src);
+extern fm_s32 rds_grp_counter_reset(struct rds_group_cnt_t *gc);
+extern fm_s32 rds_log_in(struct rds_log_t *thiz, struct rds_rx_t *new_log, fm_s32 new_len);
+extern fm_s32 rds_log_out(struct rds_log_t *thiz, struct rds_rx_t *dst, fm_s32 *dst_len);
+
+
+#define DEFINE_RDSLOG(name) \
+    struct rds_log_t name = { \
+        .size = RDS_LOG_SIZE, \
+        .in = 0, \
+        .out = 0, \
+        .len = 0, \
+        .log_in = rds_log_in, \
+        .log_out = rds_log_out, \
+    }
+
+
+#endif //__FM_RDS_H__
+
diff --git a/drivers/mtk_wcn_combo/drv_fm/inc/fm_stdlib.h b/drivers/mtk_wcn_combo/drv_fm/inc/fm_stdlib.h
new file mode 100755 (executable)
index 0000000..560ebb0
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef __FM_STDLIB_H__
+#define __FM_STDLIB_H__
+
+#include "fm_typedef.h"
+#include <linux/string.h>
+
+#if 1
+#define fm_memset(buf, a, len)  \
+({                                    \
+    void *__ret = (void*)0;              \
+    __ret = memset((buf), (a), (len)); \
+    __ret;                          \
+})
+
+#define fm_memcpy(dst, src, len)  \
+({                                    \
+    void *__ret = (void*)0;              \
+    __ret = memcpy((dst), (src), (len)); \
+    __ret;                          \
+})
+
+#define fm_malloc(len)  \
+({                                    \
+    void *__ret = (void*)0;              \
+    __ret = kmalloc(len, GFP_KERNEL); \
+    __ret;                          \
+})
+
+#define fm_zalloc(len)  \
+({                                    \
+    void *__ret = (void*)0;              \
+    __ret = kzalloc(len, GFP_KERNEL); \
+    __ret;                          \
+})
+
+#define fm_free(ptr)  kfree(ptr)
+
+#define fm_vmalloc(len)  \
+({                                    \
+    void *__ret = (void*)0;              \
+    __ret = vmalloc(len); \
+    __ret;                          \
+})
+
+#define fm_vfree(ptr)  vfree(ptr)
+
+#else
+inline void* fm_memset(void *buf, fm_s8 val, fm_s32 len)
+{
+    return memset(buf, val, len);
+}
+
+inline void* fm_memcpy(void *dst, const void *src, fm_s32 len)
+{
+    return memcpy(dst, src, len);
+}
+
+#endif
+
+#endif //__FM_STDLIB_H__
+
diff --git a/drivers/mtk_wcn_combo/drv_fm/inc/fm_typedef.h b/drivers/mtk_wcn_combo/drv_fm/inc/fm_typedef.h
new file mode 100755 (executable)
index 0000000..d601bcf
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef __FM_TYPEDEF_H__
+#define __FM_TYPEDEF_H__
+
+typedef signed char fm_s8;
+typedef signed short fm_s16;
+typedef signed int fm_s32;
+typedef signed long long fm_s64;
+typedef unsigned char fm_u8;
+typedef unsigned short fm_u16;
+typedef unsigned int fm_u32;
+typedef unsigned long long fm_u64;
+
+#ifndef FALSE
+#define FALSE (0)
+#endif
+
+#ifndef TRUE
+#define TRUE  (1)
+#endif
+
+#ifndef NULL
+#define NULL  (0)
+#endif
+
+#ifndef BOOL
+typedef unsigned char  BOOL;
+#endif
+
+typedef enum fm_bool {
+    fm_false = 0,
+    fm_true  = 1
+} fm_bool;
+
+
+#endif //__FM_TYPEDEF_H__
+
diff --git a/drivers/mtk_wcn_combo/drv_fm/inc/fm_utils.h b/drivers/mtk_wcn_combo/drv_fm/inc/fm_utils.h
new file mode 100755 (executable)
index 0000000..9c5e9f0
--- /dev/null
@@ -0,0 +1,309 @@
+#ifndef __FM_UTILS_H__
+#define __FM_UTILS_H__
+
+#include "fm_typedef.h"
+
+
+/**
+ * Base structure of fm object
+ */
+#define FM_NAME_MAX 20
+struct fm_object {
+    fm_s8              name[FM_NAME_MAX+1];                                            // name of fm object
+    fm_u8       type;                                                                  // type of fm object
+    fm_u8       flag;                                                                  // flag of fm object
+    fm_s32      ref;
+    void        *priv;
+    //struct fm_list   *list;                                                                  // list node of fm object
+};
+
+
+/*
+ * FM FIFO 
+ */
+struct fm_fifo {
+    struct fm_object obj;
+    fm_s32 size;
+    fm_s32 in;
+    fm_s32 out;
+    fm_s32 len;
+    fm_s32 item_size;
+    fm_s32 (*input)(struct fm_fifo *thiz, void *item);
+    fm_s32 (*output)(struct fm_fifo *thiz, void *item);
+    fm_bool (*is_full)(struct fm_fifo *thiz);
+    fm_bool (*is_empty)(struct fm_fifo *thiz);
+    fm_s32 (*get_total_len)(struct fm_fifo *thiz);
+    fm_s32 (*get_valid_len)(struct fm_fifo *thiz);
+    fm_s32 (*reset)(struct fm_fifo *thiz);
+};
+
+extern struct fm_fifo* fm_fifo_init(struct fm_fifo* fifo, void *buf, const fm_s8 *name, fm_s32 item_size, fm_s32 item_num); 
+
+extern struct fm_fifo* fm_fifo_create(const fm_s8 *name, fm_s32 item_size, fm_s32 item_num); 
+
+extern fm_s32 fm_fifo_release(struct fm_fifo *fifo); 
+
+#define FM_FIFO_INPUT(fifop, item)  \
+({                                    \
+    fm_s32 __ret = (fm_s32)0;              \
+    if(fifop && (fifop)->input){          \
+        __ret = (fifop)->input(fifop, item);    \
+    }                               \
+    __ret;                          \
+})
+
+#define FM_FIFO_OUTPUT(fifop, item)  \
+({                                    \
+    fm_s32 __ret = (fm_s32)0;              \
+    if(fifop && (fifop)->output){          \
+        __ret = (fifop)->output(fifop, item);    \
+    }                               \
+    __ret;                          \
+})
+
+#define FM_FIFO_IS_FULL(fifop)  \
+({                                    \
+    fm_bool __ret = fm_false;              \
+    if(fifop && (fifop)->is_full){          \
+        __ret = (fifop)->is_full(fifop);    \
+    }                               \
+    __ret;                          \
+})
+
+#define FM_FIFO_IS_EMPTY(fifop)  \
+({                                    \
+    fm_bool __ret = fm_false;              \
+    if(fifop && (fifop)->is_empty){          \
+        __ret = (fifop)->is_empty(fifop);    \
+    }                               \
+    __ret;                          \
+})
+
+#define FM_FIFO_RESET(fifop)  \
+({                                    \
+    fm_s32 __ret = (fm_s32)0;              \
+    if(fifop && (fifop)->reset){          \
+        __ret = (fifop)->reset(fifop);    \
+    }                               \
+    __ret;                          \
+})
+
+#define FM_FIFO_GET_TOTAL_LEN(fifop)  \
+({                                    \
+    fm_s32 __ret = (fm_s32)0;              \
+    if(fifop && (fifop)->get_total_len){          \
+        __ret = (fifop)->get_total_len(fifop);    \
+    }                               \
+    __ret;                          \
+})
+
+#define FM_FIFO_GET_VALID_LEN(fifop)  \
+({                                    \
+    fm_s32 __ret = (fm_s32)0;              \
+    if(fifop && (fifop)->get_valid_len){          \
+        __ret = (fifop)->get_valid_len(fifop);    \
+    }                               \
+    __ret;                          \
+})
+
+       
+/*
+ * FM asynchronous information mechanism
+ */
+struct fm_flag_event {
+    fm_s32 ref;
+    fm_s8  name[FM_NAME_MAX+1];
+    void *priv;
+
+    volatile fm_u32 flag;
+
+    //flag methods
+    fm_u32(*send)(struct fm_flag_event* thiz, fm_u32 mask);
+    fm_s32(*wait)(struct fm_flag_event* thiz, fm_u32 mask);
+    long(*wait_timeout)(struct fm_flag_event* thiz, fm_u32 mask, long timeout);
+    fm_u32(*clr)(struct fm_flag_event* thiz, fm_u32 mask);
+    fm_u32(*get)(struct fm_flag_event* thiz);
+    fm_u32(*rst)(struct fm_flag_event* thiz);
+};
+
+extern struct fm_flag_event* fm_flag_event_create(const fm_s8 *name);
+
+extern fm_s32 fm_flag_event_get(struct fm_flag_event *thiz);
+
+extern fm_s32 fm_flag_event_put(struct fm_flag_event *thiz);
+
+#define FM_EVENT_SEND(eventp, mask)  \
+({                                    \
+    fm_u32 __ret = (fm_u32)0;              \
+    if(eventp && (eventp)->send){          \
+        __ret = (eventp)->send(eventp, mask);    \
+    }                               \
+    __ret;                          \
+})
+
+#define FM_EVENT_WAIT(eventp, mask)  \
+({                                    \
+    fm_s32 __ret = (fm_s32)0;              \
+    if(eventp && (eventp)->wait){          \
+        __ret = (eventp)->wait(eventp, mask);    \
+    }                               \
+    __ret;                          \
+})
+
+#define FM_EVENT_WAIT_TIMEOUT(eventp, mask, timeout)  \
+({                                    \
+    long __ret = (long)0;              \
+    if(eventp && (eventp)->wait_timeout){          \
+        __ret = (eventp)->wait_timeout(eventp, mask, timeout);    \
+    }                               \
+    __ret;                          \
+})
+
+#define FM_EVENT_GET(eventp)  \
+({                                    \
+    fm_u32 __ret = (fm_u32)0;              \
+    if(eventp && (eventp)->get){          \
+        __ret = (eventp)->get(eventp);    \
+    }                               \
+    __ret;                          \
+})
+
+#define FM_EVENT_RESET(eventp)  \
+({                                    \
+    fm_u32 __ret = (fm_u32)0;              \
+    if(eventp && (eventp)->rst){          \
+        __ret = (eventp)->rst(eventp);    \
+    }                               \
+    __ret;                          \
+})
+
+#define FM_EVENT_CLR(eventp, mask)  \
+({                                    \
+    fm_u32 __ret = (fm_u32)0;              \
+    if(eventp && (eventp)->clr){          \
+        __ret = (eventp)->clr(eventp, mask);    \
+    }                               \
+    __ret;                          \
+})
+
+/*
+ * FM lock mechanism
+ */
+struct fm_lock {
+    fm_s8   name[FM_NAME_MAX+1];
+    fm_s32  ref;
+    void    *priv;
+
+    //lock methods
+    fm_s32(*lock)(struct fm_lock* thiz);
+       fm_s32(*trylock)(struct fm_lock *thiz,fm_s32 retryCnt);
+    fm_s32(*unlock)(struct fm_lock* thiz);
+};
+
+extern struct fm_lock* fm_lock_create(const fm_s8 *name);
+
+extern fm_s32 fm_lock_get(struct fm_lock *thiz);
+
+extern fm_s32 fm_lock_put(struct fm_lock *thiz);
+
+extern struct fm_lock* fm_spin_lock_create(const fm_s8 *name);
+
+extern fm_s32 fm_spin_lock_get(struct fm_lock *thiz);
+
+extern fm_s32 fm_spin_lock_put(struct fm_lock *thiz);
+
+#define FM_LOCK(a)         \
+({                           \
+    fm_s32 __ret = (fm_s32)0; \
+    if(a && (a)->lock){          \
+        __ret = (a)->lock(a);    \
+    }                       \
+    __ret;                   \
+})
+
+#define FM_UNLOCK(a)         \
+{                             \
+    if((a)->unlock){          \
+        (a)->unlock(a);    \
+    }                       \
+}
+
+
+/*
+ * FM timer mechanism
+ */
+enum fm_timer_ctrl {
+    FM_TIMER_CTRL_GET_TIME = 0,
+    FM_TIMER_CTRL_SET_TIME = 1,
+    FM_TIMER_CTRL_MAX
+};
+
+#define FM_TIMER_FLAG_ACTIVATED (1<<0)
+
+struct fm_timer {
+    fm_s32 ref;
+    fm_s8  name[FM_NAME_MAX+1];
+    void *priv;                                         // platform detail impliment
+
+    fm_s32 flag;                                        // timer active/inactive
+    void (*timeout_func)(unsigned long data);              //  timeout function
+    unsigned long data;                                                                        // timeout function's parameter
+    signed long timeout_ms;                                                        // timeout tick
+    //Tx parameters
+    volatile fm_u32    count;
+    volatile fm_u8     tx_pwr_ctrl_en;
+    volatile fm_u8     tx_rtc_ctrl_en;
+    volatile fm_u8     tx_desense_en;
+
+    //timer methods
+    fm_s32(*init)(struct fm_timer *thiz, void (*timeout)(unsigned long data), unsigned long data, signed long time, fm_s32 flag);
+    fm_s32(*start)(struct fm_timer *thiz);
+    fm_s32(*update)(struct fm_timer *thiz);
+    fm_s32(*stop)(struct fm_timer *thiz);
+    fm_s32(*control)(struct fm_timer *thiz, enum fm_timer_ctrl cmd, void* arg);
+};
+
+extern struct fm_timer* fm_timer_create(const fm_s8 *name);
+
+extern fm_s32 fm_timer_get(struct fm_timer *thiz);
+
+extern fm_s32 fm_timer_put(struct fm_timer *thiz);
+
+/*
+ * FM work thread mechanism
+ */
+struct fm_work {
+    fm_s32 ref;
+    fm_s8  name[FM_NAME_MAX+1];
+    void *priv;
+
+    void (*work_func)(unsigned long data);
+    unsigned long data;
+    //work methods
+    fm_s32(*init)(struct fm_work *thiz, void (*work_func)(unsigned long data), unsigned long data);
+};
+
+extern struct fm_work* fm_work_create(const fm_s8 *name);
+
+extern fm_s32 fm_work_get(struct fm_work *thiz);
+
+extern fm_s32 fm_work_put(struct fm_work *thiz);
+
+
+struct fm_workthread {
+    fm_s32 ref;
+    fm_s8  name[FM_NAME_MAX+1];
+    void *priv;
+
+    //workthread methods
+    fm_s32(*add_work)(struct fm_workthread *thiz, struct fm_work *work);
+};
+
+extern struct fm_workthread* fm_workthread_create(const fm_s8* name);
+
+extern fm_s32 fm_workthread_get(struct fm_workthread *thiz);
+
+extern fm_s32 fm_workthread_put(struct fm_workthread *thiz);
+
+#endif //__FM_UTILS_H__
+
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6620/inc/mt6620_drv_dsp.h b/drivers/mtk_wcn_combo/drv_fm/mt6620/inc/mt6620_drv_dsp.h
new file mode 100755 (executable)
index 0000000..8b13789
--- /dev/null
@@ -0,0 +1 @@
+
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6620/inc/mt6620_fm.h b/drivers/mtk_wcn_combo/drv_fm/mt6620/inc/mt6620_fm.h
new file mode 100755 (executable)
index 0000000..1a2e544
--- /dev/null
@@ -0,0 +1,54 @@
+/* mt6620_fm.h
+ *
+ * (C) Copyright 2011 
+ * MediaTek <www.MediaTek.com>
+ * Hongcheng <hongcheng.xia@MediaTek.com>
+ *
+ * MT6620 FM Radio Driver --  head file
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __MT6620_FM_H__
+#define __MT6620_FM_H__
+
+#include "fm_typedef.h"
+
+//#define FM_PowerOn_with_ShortAntenna
+#define MT6620_RSSI_TH_LONG    0xFF01      //FM radio long antenna RSSI threshold(11.375dBuV)
+#define MT6620_RSSI_TH_SHORT   0xFEE0      //FM radio short antenna RSSI threshold(-1dBuV)
+#define MT6620_CQI_TH          0x00E9      //FM radio Channel quality indicator threshold(0x0000~0x00FF)
+#define MT6620_SEEK_SPACE      1           //FM radio seek space,1:100KHZ; 2:200KHZ
+#define MT6620_SCAN_CH_SIZE    40          //FM radio scan max channel size
+#define MT6620_BAND            1           //FM radio band, 1:87.5MHz~108.0MHz; 2:76.0MHz~90.0MHz; 3:76.0MHz~108.0MHz; 4:special
+#define MT6620_BAND_FREQ_L     875         //FM radio special band low freq(Default 87.5MHz)
+#define MT6620_BAND_FREQ_H     1080        //FM radio special band high freq(Default 108.0MHz)
+#define MT6620_DEEMPHASIS_50us TRUE
+
+#define MT6620_SLAVE_ADDR    0xE0      //0x70 7-bit address
+#define MT6620_MAX_COUNT     100
+#define MT6620_SCANTBL_SIZE  16                //16*uinit16_t
+
+#define AFC_ON  0x01
+#if AFC_ON
+#define FM_MAIN_CTRL_INIT  0x480
+#else
+#define FM_MAIN_CTRL_INIT  0x080
+#endif
+
+#define ext_clk                                //if define ext_clk use external reference clock or mask will use internal
+#define MT6620_DEV                     "MT6620"   
+
+#endif //end of #ifndef __MT6620_FM_H__
+
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6620/inc/mt6620_fm_cmd.h b/drivers/mtk_wcn_combo/drv_fm/mt6620/inc/mt6620_fm_cmd.h
new file mode 100755 (executable)
index 0000000..4a00dc9
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef __MT6620_FM_CMD_H__
+#define __MT6620_FM_CMD_H__
+
+#include <linux/types.h>
+#include "fm_typedef.h"
+
+/* FM basic-operation's opcode */
+#define FM_BOP_BASE (0x80)
+enum {
+    FM_WRITE_BASIC_OP       = (FM_BOP_BASE + 0x00),
+    FM_UDELAY_BASIC_OP      = (FM_BOP_BASE + 0x01),
+    FM_RD_UNTIL_BASIC_OP    = (FM_BOP_BASE + 0x02),
+    FM_MODIFY_BASIC_OP      = (FM_BOP_BASE + 0x03),
+    FM_MSLEEP_BASIC_OP      = (FM_BOP_BASE + 0x04),
+    FM_MAX_BASIC_OP         = (FM_BOP_BASE + 0x05)
+};
+
+/* FM BOP's size */
+#define FM_WRITE_BASIC_OP_SIZE      (3)
+#define FM_UDELAY_BASIC_OP_SIZE     (4)
+#define FM_RD_UNTIL_BASIC_OP_SIZE   (5)
+#define FM_MODIFY_BASIC_OP_SIZE     (5)
+#define FM_MSLEEP_BASIC_OP_SIZE     (4)
+
+fm_s32 mt6620_off_2_longANA_1(fm_u8 *buf, fm_s32 buf_size);
+fm_s32 mt6620_off_2_longANA_2(fm_u8 *buf, fm_s32 buf_size);
+
+fm_s32 mt6620_pwrup_digital_init_1(fm_u8 *buf, fm_s32 buf_size);
+fm_s32 mt6620_pwrup_digital_init_2(fm_u8 *buf, fm_s32 buf_size);
+fm_s32 mt6620_pwrup_digital_init_3(fm_u8 *buf, fm_s32 buf_size);
+
+fm_s32 mt6620_pwrdown(fm_u8 *buf, fm_s32 buf_size);
+fm_s32 mt6620_rampdown(fm_u8 *buf, fm_s32 buf_size);
+
+fm_s32 mt6620_tune_1(fm_u8 *buf, fm_s32 buf_size, fm_u16 freq);
+fm_s32 mt6620_tune_2(fm_u8 *buf, fm_s32 buf_size, fm_u16 freq);
+fm_s32 mt6620_tune_3(fm_u8 *buf, fm_s32 buf_size, fm_u16 freq);
+fm_s32 mt6620_fast_tune(fm_u8 *tx_buf, fm_s32 tx_buf_size, fm_u16 freq);
+fm_s32 mt6620_full_cqi_req(fm_u8 *buf, fm_s32 buf_size, fm_u16 freq, fm_s32 cnt, fm_s32 type);
+
+fm_s32 mt6620_seek_1(fm_u8 *buf, fm_s32 buf_size, fm_u16 seekdir, fm_u16 space, fm_u16 max_freq, fm_u16 min_freq);
+fm_s32 mt6620_seek_2(fm_u8 *buf, fm_s32 buf_size, fm_u16 seekdir, fm_u16 space, fm_u16 max_freq, fm_u16 min_freq);
+
+fm_s32 mt6620_scan_1(fm_u8 *buf, fm_s32 buf_size, fm_u16 scandir, fm_u16 space, fm_u16 max_freq, fm_u16 min_freq);
+fm_s32 mt6620_scan_2(fm_u8 *buf, fm_s32 buf_size, fm_u16 scandir, fm_u16 space, fm_u16 max_freq, fm_u16 min_freq);
+
+fm_s32 mt6620_get_reg(fm_u8 *buf, fm_s32 buf_size, fm_u8 addr);
+fm_s32 mt6620_set_reg(fm_u8 *buf, fm_s32 buf_size, fm_u8 addr, fm_u16 value);
+fm_s32 mt6620_rampdown_tx(unsigned char *tx_buf, int tx_buf_size);
+fm_s32 mt6620_tune_txscan(unsigned char *tx_buf, int tx_buf_size, uint16_t freq);
+fm_s32 mt6620_tune_tx(unsigned char *tx_buf, int tx_buf_size, uint16_t freq);
+fm_s32 mt6620_rds_rx_enable(unsigned char *tx_buf, int tx_buf_size);
+fm_s32 mt6620_rds_rx_disable(unsigned char *tx_buf, int tx_buf_size);
+fm_s32 mt6620_rds_tx(unsigned char *tx_buf, int tx_buf_size, uint16_t pi, uint16_t *ps, uint16_t *other_rds, uint8_t other_rds_cnt);
+fm_s32 mt6620_off_2_tx_shortANA(fm_u8 *tx_buf, fm_s32 tx_buf_size);
+fm_s32 mt6620_dig_init(fm_u8 *tx_buf, fm_s32 tx_buf_size);
+
+extern fm_s32 fm_get_channel_space(int freq);
+
+#endif
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6620/inc/mt6620_fm_lib.h b/drivers/mtk_wcn_combo/drv_fm/mt6620/inc/mt6620_fm_lib.h
new file mode 100755 (executable)
index 0000000..b2c0910
--- /dev/null
@@ -0,0 +1,135 @@
+#ifndef __MT6620_FM_LIB_H__
+#define __MT6620_FM_LIB_H__
+
+#include "fm_typedef.h"
+
+#define MT6620_VOL_MAX   0x2B  // 43 volume(0-15)
+enum {
+    DSPPATCH = 0xFFF9,
+    USDELAY = 0xFFFA,
+    MSDELAY = 0xFFFB,
+    HW_VER = 0xFFFD,
+    POLL_N = 0xFFFE, //poling check if bit(n) is '0'
+    POLL_P = 0xFFFF, //polling check if bit(n) is '1'
+};
+
+enum {
+    FM_PUS_DSPPATCH = DSPPATCH,
+    FM_PUS_USDELAY = USDELAY,
+    FM_PUS_MSDELAY = MSDELAY,
+    FM_PUS_HW_VER = HW_VER,
+    FM_PUS_POLL_N = POLL_N, //poling check if bit(n) is '0'
+    FM_PUS_POLL_P = POLL_P, //polling check if bit(n) is '1'
+    FM_PUS_MAX
+};
+
+enum {
+    DSP_PATH = 0x02,
+    DSP_COEFF = 0x03,
+    DSP_HW_COEFF = 0x04
+};
+
+enum IMG_TYPE {
+    IMG_WRONG = 0,
+    IMG_ROM,
+    IMG_PATCH,
+    IMG_COEFFICIENT,
+    IMG_HW_COEFFICIENT
+};
+
+enum {
+    mt6620_E1 = 0,
+    mt6620_E2
+};
+
+/*enum {
+    FM_LONG_ANA = 0,
+    FM_SHORT_ANA
+};*/
+enum {
+    MT6620_I2S_ON = 0,
+    MT6620_I2S_OFF
+};
+
+enum {
+    MT6620_I2S_MASTER = 0,
+    MT6620_I2S_SLAVE
+};
+
+enum {
+    MT6620_I2S_32K = 0,
+    MT6620_I2S_44K,
+    MT6620_I2S_48K
+};
+
+struct mt6620_fm_i2s_info {
+    fm_s32 status;
+    fm_s32 mode;
+    fm_s32 rate;
+};
+struct mt6620_fm_softmute_tune_cqi_t 
+{  
+       fm_u16 ch;                              //current frequency
+       fm_u16 rssi;              // RSSI of current channel (raw data)
+       fm_u16 pamd;              // PAMD of current channel (raw data)
+       fm_u16 mr;              // MR of current channel (raw data)
+       fm_u16 atdc;              // ATDC of current channel (raw data)
+       fm_u16 prx;              // PRX of current channel (raw data)
+       fm_u16 smg;              // soft mute gain of current channel (raw data)
+};
+
+#define BITn(n) (uint16_t)(1<<(n))
+#define MASK(n) (uint16_t)(~(1<<(n)))
+//#define HiSideTableSize 1
+#define FM_TX_PWR_CTRL_FREQ_THR 890
+#define FM_TX_PWR_CTRL_TMP_THR_UP 45
+#define FM_TX_PWR_CTRL_TMP_THR_DOWN 0
+
+#define FM_TX_TRACKING_TIME_MAX 10000 //TX VCO tracking time, default 100ms
+
+//#define MT6620_FPGA
+//#define FM_MAIN_PGSEL   (0x9F)
+/*
+#define FM_MAIN_BASE            (0x0)
+#define FM_MAIN_BITMAP0         (FM_MAIN_BASE + 0x80)
+#define FM_MAIN_BITMAP1         (FM_MAIN_BASE + 0x81)
+#define FM_MAIN_BITMAP2         (FM_MAIN_BASE + 0x82)
+#define FM_MAIN_BITMAP3         (FM_MAIN_BASE + 0x83)
+#define FM_MAIN_BITMAP4         (FM_MAIN_BASE + 0x84)
+#define FM_MAIN_BITMAP5         (FM_MAIN_BASE + 0x85)
+#define FM_MAIN_BITMAP6         (FM_MAIN_BASE + 0x86)
+#define FM_MAIN_BITMAP7         (FM_MAIN_BASE + 0x87)
+#define FM_MAIN_BITMAP8         (FM_MAIN_BASE + 0x88)
+#define FM_MAIN_BITMAP9         (FM_MAIN_BASE + 0x89)
+#define FM_MAIN_BITMAPA         (FM_MAIN_BASE + 0x8a)
+#define FM_MAIN_BITMAPB         (FM_MAIN_BASE + 0x8b)
+#define FM_MAIN_BITMAPC         (FM_MAIN_BASE + 0x8c)
+#define FM_MAIN_BITMAPD         (FM_MAIN_BASE + 0x8d)
+#define FM_MAIN_BITMAPE         (FM_MAIN_BASE + 0x8e)
+#define FM_MAIN_BITMAPF         (FM_MAIN_BASE + 0x8f)
+*/
+enum group_idx {
+       mono = 0,
+       stereo,
+       RSSI_threshold,
+       HCC_Enable,
+       PAMD_threshold,
+       Softmute_Enable,
+       De_emphasis,
+       HL_Side,
+       Demod_BW,
+       Dynamic_Limiter,
+       Softmute_Rate,
+       AFC_Enable,
+       Softmute_Level,
+       Analog_Volume,
+       GROUP_TOTAL_NUMS
+};
+
+enum item_idx {
+       Sblend_OFF = 0,
+       Sblend_ON,
+       ITEM_TOTAL_NUMS
+};
+       
+#endif
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6620/inc/mt6620_fm_link.h b/drivers/mtk_wcn_combo/drv_fm/mt6620/inc/mt6620_fm_link.h
new file mode 100755 (executable)
index 0000000..42a5ebb
--- /dev/null
@@ -0,0 +1,74 @@
+/* mt6620_fm_link.h
+ *
+ * (C) Copyright 2011
+ * MediaTek <www.MediaTek.com>
+ * Hongcheng <hongcheng.xia@MediaTek.com>
+ *
+ * MT6620 FM Radio Driver -- setup data link
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __MT6620_FM_LINK_H__
+#define __MT6620_FM_LINK_H__
+#if 0
+#include <linux/wait.h>
+#include "fm_link.h"
+
+#define RX_BUF_SIZE 128
+#define TX_BUF_SIZE 1024
+
+#define SW_RETRY_CNT            (2)
+#define SW_RETRY_CNT_MAX        (5)
+#define SW_WAIT_TIMEOUT_MAX     (100)
+
+// FM operation timeout define for error handle
+#define TEST_TIMEOUT            (3)
+#define FSPI_EN_TIMEOUT         (3)
+#define FSPI_MUXSEL_TIMEOUT     (3)
+#define FSPI_RD_TIMEOUT         (3)
+#define FSPI_WR_TIMEOUT         (3)
+#define I2C_RD_TIMEOUT          (3)
+#define I2C_WR_TIMEOUT          (3)
+#define EN_TIMEOUT              (10)
+#define RST_TIMEOUT             (3)
+#define TUNE_TIMEOUT            (3)
+#define SEEK_TIMEOUT            (15)
+#define SCAN_TIMEOUT            (15) //usualy scan will cost 10 seconds 
+#define RDS_RX_EN_TIMEOUT       (3)
+#define RDS_DATA_TIMEOUT        (100)
+#define RAMPDOWN_TIMEOUT        (3)
+#define MCUCLK_TIMEOUT          (3)
+#define MODEMCLK_TIMEOUT        (3)
+#define RDS_TX_TIMEOUT          (3)
+#define PATCH_TIMEOUT           (5)
+#define COEFF_TIMEOUT           (5)
+#define HWCOEFF_TIMEOUT         (5)
+#define ROM_TIMEOUT             (5)
+
+struct fm_link_event {
+    //data
+    volatile fm_u32 flag;
+    wait_queue_head_t wq;
+    struct fm_res_ctx result; // seek/scan/read/RDS
+    //methods
+    fm_u32(*set)(struct fm_link_event* thiz, fm_u32 mask);
+    fm_u32(*clr)(struct fm_link_event* thiz, fm_u32 mask);
+    long(*check)(struct fm_link_event* thiz, fm_u32 mask, long timeout);
+    fm_u32(*get)(struct fm_link_event* thiz);
+    fm_u32(*rst)(struct fm_link_event* thiz);
+};
+#endif
+#endif
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6620/inc/mt6620_fm_reg.h b/drivers/mtk_wcn_combo/drv_fm/mt6620/inc/mt6620_fm_reg.h
new file mode 100755 (executable)
index 0000000..ce1f788
--- /dev/null
@@ -0,0 +1,98 @@
+#ifndef __MT6620_FM_REG_H__
+#define __MT6620_FM_REG_H__
+
+enum MT6620_REG{ 
+       FM_MAIN_CG1_CTRL = 0x60,
+       FM_MAIN_CG2_CTRL = 0x61,
+    FM_MAIN_HWVER = 0x62,
+    FM_MAIN_CTRL = 0x63,
+    FM_CHANNEL_SET = 0x65,
+    FM_MAIN_CFG1 = 0x66,
+    FM_MAIN_CFG2 = 0x67,
+    FM_MAIN_MCLKDESENSE = 0x38,
+    FM_MAIN_INTR = 0x69,
+    FM_MAIN_INTRMASK = 0x6A,
+    FM_MAIN_EXTINTRMASK = 0x6B,
+    FM_RSSI_IND = 0xE8,
+    FM_RSSI_TH = 0x6D,
+    FM_MAIN_RESET = 0x6E,
+    FM_MAIN_CHANDETSTAT = 0x6F,  
+    FM_RDS_CFG0 = 0x80,
+    FM_RDS_INFO = 0x81,
+    FM_RDS_DATA_REG = 0x82,
+    FM_RDS_GOODBK_CNT = 0xC6, //page3 0xC6
+    FM_RDS_BADBK_CNT = 0xC7,  //page3 0xC7
+    FM_RDS_PWDI = 0x85,
+    FM_RDS_PWDQ = 0x86,
+    FM_RDS_FIFO_STATUS0 = 0x87,
+    FM_FT_CON9 = 0x8F,
+       FM_DSP_PATCH_CTRL = 0x90,
+       FM_DSP_PATCH_OFFSET = 0x91,
+       FM_DSP_PATCH_DATA = 0x92,
+       FM_DSP_MEM_CTRL4 = 0x93,
+       FM_MAIN_PGSEL = 0x9F,
+       FM_ADDR_PAMD = 0xE9,
+       FM_RDS_BDGRP_ABD_CTRL_REG = 0xB6,
+       FM_RDS_POINTER = 0xF0,   
+       FM_MR_IND = 0xF2,        
+};
+#define FM_TXSCAN_RSSI_TH      (-250)
+#define FM_TXSCAN_PAMD_TH      (-20)
+#define FM_TXSCAN_MR_TH                (-38)
+
+//RDS_BDGRP_ABD_CTRL_REG
+enum{
+       BDGRP_ABD_EN = 0x0001,
+       BER_RUN = 0x2000
+};
+#define FM_DAC_CON1 0x83
+#define FM_DAC_CON2 0x84
+#define FM_FT_CON0 0x86
+#define FM_I2S_CON0 0x90
+#define FM_STEROMONO_CTR (0xE0)
+enum{
+       FT_EN = 0x0001
+};
+          
+enum{
+       I2S_EN = 0x0001,
+       FORMAT = 0x0002,
+       WLEN = 0x0004,
+       I2S_SRC = 0x0008
+};
+
+//FM_MAIN_CTRL
+enum{
+       TUNE = 0x0001,
+       SEEK = 0x0002,
+       SCAN = 0x0004,
+       RDS_MASK = 0x0010,
+       MUTE = 0x0020,
+       RDS_BRST = 0x0040,
+       RAMP_DOWN = 0x0100,
+};
+
+//FM_MAIN_INTR
+enum{
+       FM_INTR_STC_DONE = 0x0001,
+       FM_INTR_IQCAL_DONE = 0x0002,                            
+       FM_INTR_DESENSE_HIT     = 0x0004,                               
+       FM_INTR_CHNL_CHG = 0x0008,                              
+       FM_INTR_SW_INTR = 0x0010,       
+       FM_INTR_RDS = 0x0020
+};
+
+enum{
+       ANTENNA_TYPE = 0x0010,
+};
+//FM reg page
+enum FM_PAGE{
+    FM_PG0 = 0,
+    FM_PG1,
+    FM_PG2,
+    FM_PG3,
+    FM_PGMAX
+};
+
+#endif //__MT6620_FM_REG_H__
+
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6620/pub/mt6620_fm_cmd.c b/drivers/mtk_wcn_combo/drv_fm/mt6620/pub/mt6620_fm_cmd.c
new file mode 100755 (executable)
index 0000000..00ecfab
--- /dev/null
@@ -0,0 +1,1482 @@
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include "fm_typedef.h"
+#include "fm_dbg.h"
+#include "fm_err.h"
+#include "fm_rds.h"
+#include "fm_link.h"
+
+#include "mt6620_fm_reg.h"
+//#include "mt6620_fm_link.h"
+#include "mt6620_fm.h"
+#include "mt6620_fm_cmd.h"
+#include "mt6620_fm_cust_cfg.h"
+
+static fm_s32 fm_bop_write(fm_u8 addr, fm_u16 value, fm_u8 *buf, fm_s32 size)
+{
+    if (size < (FM_WRITE_BASIC_OP_SIZE + 2)) {
+        return (-1);
+    }
+
+    if (buf == NULL) {
+        return (-2);
+    }
+
+    buf[0] = FM_WRITE_BASIC_OP;
+    buf[1] = FM_WRITE_BASIC_OP_SIZE;
+    buf[2] = addr;
+    buf[3] = (fm_u8)((value) & 0x00FF);
+    buf[4] = (fm_u8)((value >> 8) & 0x00FF);
+
+    WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4]);
+
+    return (FM_WRITE_BASIC_OP_SIZE + 2);
+}
+
+static fm_s32 fm_bop_udelay(fm_u32 value, fm_u8 *buf, fm_s32 size)
+{
+    if (size < (FM_UDELAY_BASIC_OP_SIZE + 2)) {
+        return (-1);
+    }
+
+    if (buf == NULL) {
+        return (-2);
+    }
+
+    buf[0] = FM_UDELAY_BASIC_OP;
+    buf[1] = FM_UDELAY_BASIC_OP_SIZE;
+    buf[2] = (fm_u8)((value) & 0x000000FF);
+    buf[3] = (fm_u8)((value >> 8) & 0x000000FF);
+    buf[4] = (fm_u8)((value >> 16) & 0x000000FF);
+    buf[5] = (fm_u8)((value >> 24) & 0x000000FF);
+
+    WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
+
+    return (FM_UDELAY_BASIC_OP_SIZE + 2);
+}
+
+static fm_s32 fm_bop_rd_until(fm_u8 addr, fm_u16 mask, fm_u16 value, fm_u8 *buf, fm_s32 size)
+{
+    if (size < (FM_RD_UNTIL_BASIC_OP_SIZE + 2)) {
+        return (-1);
+    }
+
+    if (buf == NULL) {
+        return (-2);
+    }
+
+    buf[0] = FM_RD_UNTIL_BASIC_OP;
+    buf[1] = FM_RD_UNTIL_BASIC_OP_SIZE;
+    buf[2] = addr;
+    buf[3] = (fm_u8)((mask) & 0x00FF);
+    buf[4] = (fm_u8)((mask >> 8) & 0x00FF);
+    buf[5] = (fm_u8)((value) & 0x00FF);
+    buf[6] = (fm_u8)((value >> 8) & 0x00FF);
+
+    WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
+
+    return (FM_RD_UNTIL_BASIC_OP_SIZE + 2);
+}
+
+static fm_s32 fm_bop_modify(fm_u8 addr, fm_u16 mask_and, fm_u16 mask_or, fm_u8 *buf, fm_s32 size)
+{
+    if (size < (FM_MODIFY_BASIC_OP_SIZE + 2)) {
+        return (-1);
+    }
+
+    if (buf == NULL) {
+        return (-2);
+    }
+
+    buf[0] = FM_MODIFY_BASIC_OP;
+    buf[1] = FM_MODIFY_BASIC_OP_SIZE;
+    buf[2] = addr;
+    buf[3] = (fm_u8)((mask_and) & 0x00FF);
+    buf[4] = (fm_u8)((mask_and >> 8) & 0x00FF);
+    buf[5] = (fm_u8)((mask_or) & 0x00FF);
+    buf[6] = (fm_u8)((mask_or >> 8) & 0x00FF);
+
+    WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
+
+    return (FM_MODIFY_BASIC_OP_SIZE + 2);
+}
+
+
+/*
+ * mt6620_pwrup_clock_on - Wholechip FM Power Up: step 1, FM Digital Clock enable
+ * @buf - target buf
+ * @buf_size - buffer size
+ * return package size
+ */
+fm_s32 mt6620_off_2_longANA_1(fm_u8 *buf, fm_s32 buf_size)
+{
+    fm_s32 pkt_size = 0;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_ENABLE_OPCODE;
+    pkt_size = 4;
+
+    //A01 Turn on the bandgap and central biasing core
+    pkt_size += fm_bop_write(0x01, 0x4A00, &buf[pkt_size], buf_size - pkt_size);//wr 1 4A00
+    pkt_size += fm_bop_udelay(30, &buf[pkt_size], buf_size - pkt_size);//delay 30
+    pkt_size += fm_bop_write(0x01, 0x6A00, &buf[pkt_size], buf_size - pkt_size);//wr 1 6A00
+    pkt_size += fm_bop_udelay(50, &buf[pkt_size], buf_size - pkt_size);//delay 50
+    //A02 Initialise the LDO's Output
+    pkt_size += fm_bop_write(0x02, 0x299C, &buf[pkt_size], buf_size - pkt_size);//wr 2 299C
+    //A03 Enable RX, ADC and ADPLL LDO
+    pkt_size += fm_bop_write(0x01, 0x6B82, &buf[pkt_size], buf_size - pkt_size);//wr 1 6B82
+    //A04 Update FMRF optimized register settings
+    pkt_size += fm_bop_write(0x04, 0x0142, &buf[pkt_size], buf_size - pkt_size);//wr 4 0142
+    pkt_size += fm_bop_write(0x05, 0x00E7, &buf[pkt_size], buf_size - pkt_size);//wr 5 00E7
+    pkt_size += fm_bop_write(0x0A, 0x0060, &buf[pkt_size], buf_size - pkt_size);//wr a 0060
+    pkt_size += fm_bop_write(0x0C, 0xA88C, &buf[pkt_size], buf_size - pkt_size);//wr c A88C
+    pkt_size += fm_bop_write(0x0D, 0x0888, &buf[pkt_size], buf_size - pkt_size);//wr d 0888
+    pkt_size += fm_bop_write(0x10, 0x1E8D, &buf[pkt_size], buf_size - pkt_size);//wr 10 1E8D
+    pkt_size += fm_bop_write(0x27, 0x0005, &buf[pkt_size], buf_size - pkt_size);//wr 27 0005
+    pkt_size += fm_bop_write(0x0E, 0x0040, &buf[pkt_size], buf_size - pkt_size);//wr e 0040
+    pkt_size += fm_bop_write(0x03, 0x50F0, &buf[pkt_size], buf_size - pkt_size);//wr 3 50f0
+    pkt_size += fm_bop_write(0x3F, 0xAD06, &buf[pkt_size], buf_size - pkt_size);//wr 3f AD06
+    pkt_size += fm_bop_write(0x3E, 0x3280, &buf[pkt_size], buf_size - pkt_size);//wr 3e 3280
+    pkt_size += fm_bop_write(0x06, 0x0124, &buf[pkt_size], buf_size - pkt_size);//wr 6 0124
+    pkt_size += fm_bop_write(0x08, 0x15B8, &buf[pkt_size], buf_size - pkt_size);//wr 8 15B8
+    //A05 Enable RX related blocks
+    pkt_size += fm_bop_write(0x28, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 28 0000
+    pkt_size += fm_bop_write(0x00, 0x0166, &buf[pkt_size], buf_size - pkt_size);//wr 0 0166
+    pkt_size += fm_bop_write(0x3A, 0x0004, &buf[pkt_size], buf_size - pkt_size);//wr 3a 0004
+    pkt_size += fm_bop_write(0x37, 0x2590, &buf[pkt_size], buf_size - pkt_size);//wr 37 2590
+    // FM ADPLL Power Up
+    // () for 16.384M mode, otherwise 15.36M
+    pkt_size += fm_bop_write(0x25, 0x040F, &buf[pkt_size], buf_size - pkt_size);//wr 25 040f
+    pkt_size += fm_bop_write(0x20, 0x2720, &buf[pkt_size], buf_size - pkt_size);//wr 20 2720
+    //XHC, 2011/03/18, [wr 22 9980->6680]
+    pkt_size += fm_bop_write(0x22, 0x6680, &buf[pkt_size], buf_size - pkt_size);//wr 22 9980
+    pkt_size += fm_bop_write(0x25, 0x080F, &buf[pkt_size], buf_size - pkt_size);//wr 25 080f
+    pkt_size += fm_bop_write(0x1E, 0x0863, &buf[pkt_size], buf_size - pkt_size);//wr 1e 0863(0A63)
+    pkt_size += fm_bop_udelay(5000, &buf[pkt_size], buf_size - pkt_size);//delay 5000
+    pkt_size += fm_bop_write(0x1E, 0x0865, &buf[pkt_size], buf_size - pkt_size);//wr 1e 0865 (0A65)
+    pkt_size += fm_bop_udelay(5000, &buf[pkt_size], buf_size - pkt_size);//delay 5000
+    pkt_size += fm_bop_write(0x1E, 0x0871, &buf[pkt_size], buf_size - pkt_size);//wr 1e 0871 (0A71)
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+fm_s32 mt6620_off_2_longANA_2(fm_u8 *buf, fm_s32 buf_size)
+{
+    fm_s32 pkt_size = 0;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_ENABLE_OPCODE;
+    pkt_size = 4;
+
+    pkt_size += fm_bop_udelay(100000, &buf[pkt_size], buf_size - pkt_size);//delay 100000
+    pkt_size += fm_bop_write(0x2A, 0x1026, &buf[pkt_size], buf_size - pkt_size);//wr 2a 1026
+    // FM RC Calibration
+    pkt_size += fm_bop_write(0x00, 0x01E6, &buf[pkt_size], buf_size - pkt_size);//wr 0 01E6
+    pkt_size += fm_bop_udelay(1, &buf[pkt_size], buf_size - pkt_size);//delay 1
+    pkt_size += fm_bop_write(0x1B, 0x0094, &buf[pkt_size], buf_size - pkt_size);//wr 1b 0094
+    pkt_size += fm_bop_write(0x1B, 0x0095, &buf[pkt_size], buf_size - pkt_size);//wr 1b 0095
+    pkt_size += fm_bop_udelay(200, &buf[pkt_size], buf_size - pkt_size);//delay 200
+    pkt_size += fm_bop_write(0x1B, 0x0094, &buf[pkt_size], buf_size - pkt_size);//wr 1b 0094
+    pkt_size += fm_bop_write(0x00, 0x0166, &buf[pkt_size], buf_size - pkt_size);//wr 0 0166
+    // FM VCO Enable
+    pkt_size += fm_bop_write(0x01, 0x6B8A, &buf[pkt_size], buf_size - pkt_size);//wr 1 6B8A
+    pkt_size += fm_bop_udelay(1, &buf[pkt_size], buf_size - pkt_size);//delay 1
+    pkt_size += fm_bop_write(0x00, 0xC166, &buf[pkt_size], buf_size - pkt_size);//wr 0 C166
+    pkt_size += fm_bop_udelay(3000, &buf[pkt_size], buf_size - pkt_size);//delay 3000
+    pkt_size += fm_bop_write(0x00, 0xF166, &buf[pkt_size], buf_size - pkt_size);//wr 0 F166
+    pkt_size += fm_bop_write(0x09, 0x2964, &buf[pkt_size], buf_size - pkt_size);//wr 9 2964
+    // FM RFDIG settings
+    pkt_size += fm_bop_write(0x2E, 0x0008, &buf[pkt_size], buf_size - pkt_size);//wr 2e 8
+    pkt_size += fm_bop_write(0x2B, 0x0064, &buf[pkt_size], buf_size - pkt_size);//wr 2b 64
+    pkt_size += fm_bop_write(0x2C, 0x0032, &buf[pkt_size], buf_size - pkt_size);//wr 2c 32
+    pkt_size += fm_bop_write(0x11, 0x17d4, &buf[pkt_size], buf_size - pkt_size);//wr 11 17d4
+    //Update dynamic subband switching setting, XHC 2011/05/17
+    pkt_size += fm_bop_write(0x13, 0xFA00, &buf[pkt_size], buf_size - pkt_size);//wr 13 FA00
+    pkt_size += fm_bop_write(0x14, 0x0580, &buf[pkt_size], buf_size - pkt_size);//wr 14 0580
+    pkt_size += fm_bop_write(0x15, 0xFA80, &buf[pkt_size], buf_size - pkt_size);//wr 15 FA80
+    pkt_size += fm_bop_write(0x16, 0x0580, &buf[pkt_size], buf_size - pkt_size);//wr 16 0580
+    pkt_size += fm_bop_write(0x33, 0x0008, &buf[pkt_size], buf_size - pkt_size);//wr 33 0008
+    // FM DCOC Calibration
+    pkt_size += fm_bop_write(0x64, 0x0001, &buf[pkt_size], buf_size - pkt_size);//wr 64 1
+    pkt_size += fm_bop_write(0x63, 0x0020, &buf[pkt_size], buf_size - pkt_size);//wr 63 20
+    pkt_size += fm_bop_write(0x9C, 0x0044, &buf[pkt_size], buf_size - pkt_size);//wr 9C 0044
+    //pkt_size += fm_bop_write(0x6B, 0x0100, &buf[pkt_size], buf_size - pkt_size);//"Disable other interrupts except for STC_DONE(dependent on interrupt output source selection)"
+    pkt_size += fm_bop_write(0x0F, 0x1A08, &buf[pkt_size], buf_size - pkt_size);//wr F 1A08
+    pkt_size += fm_bop_write(0x63, 0x0021, &buf[pkt_size], buf_size - pkt_size);//wr 63 21
+    pkt_size += fm_bop_rd_until(0x69, 0x0001, 0x0001, &buf[pkt_size], buf_size - pkt_size);//Poll fm_intr_stc_done (69H D0) = 1
+    pkt_size += fm_bop_write(0x69, 0x0001, &buf[pkt_size], buf_size - pkt_size);//wr 69 1
+    pkt_size += fm_bop_write(0x63, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 63 0
+    pkt_size += fm_bop_rd_until(0x6F, 0x0001, 0x0000, &buf[pkt_size], buf_size - pkt_size);//Poll stc_done (6FH D0)= 0
+    // Others
+    pkt_size += fm_bop_write(0x00, 0xF167, &buf[pkt_size], buf_size - pkt_size);//wr 0 F167
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+fm_s32 mt6620_rx_digital_init(fm_u8 *tx_buf, fm_s32 tx_buf_size)
+{
+    fm_s32 pkt_size = 0;
+
+    if(tx_buf_size < TX_BUF_SIZE){
+        return (-1);
+    }
+    
+    tx_buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    tx_buf[1] = FM_ENABLE_OPCODE;
+    pkt_size = 4;
+
+    // fm_rgf_maincon
+    //rd 62
+    pkt_size += fm_bop_write(0x65, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 65 0
+    pkt_size += fm_bop_write(0x64, 0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 64 1
+    pkt_size += fm_bop_write(0x63, 0x0480, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 63 480
+    pkt_size += fm_bop_write(0x6D, 0x1AB2, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 6d 1ab2
+    pkt_size += fm_bop_write(0x6B, 0x2100, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 6b 2100
+    pkt_size += fm_bop_write(0x68, 0xE100, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 68 E100
+    pkt_size += fm_bop_udelay(10000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 10000
+    pkt_size += fm_bop_write(0x68, 0xE000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 68 E000
+    // fm_rgf_dac
+    pkt_size += fm_bop_write(0x9C, 0xab48, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9c ab48
+    pkt_size += fm_bop_write(0x9E, 0x000C, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9e c
+    pkt_size += fm_bop_write(0x71, 0x807f, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 71 807f
+    pkt_size += fm_bop_write(0x72, 0x878f, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 72 878f
+    //XHC, 2011/04/29 update 0x73 form 0x07C3 to 0x07C1 speed up I/Q calibration
+    pkt_size += fm_bop_write(0x73, 0x07c1, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 73 7c3
+    // fm_rgf_front
+    pkt_size += fm_bop_write(0x9F, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9f 0
+    pkt_size += fm_bop_write(0xCB, 0x00B0, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr cb b0
+    //XHC, 2011/05/06 FM RSSI config
+//    pkt_size += fm_bop_write(0xE0, ((0xA301 & 0xFC00) | (FMR_RSSI_TH_LONG & 0x03FF)), &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr e0 a301
+//    pkt_size += fm_bop_write(0xE1, ((0x00E9 & 0xFF00) | (FMR_CQI_TH & 0x00FF)), &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr e1 D0~D7, PAMD TH
+       //Run,2013/01 smt scan, ignore this
+    pkt_size += fm_bop_write(0xE0, ((0xA301 & 0xFC00) | (0x0301 & 0x03FF)), &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr e0 a301
+    pkt_size += fm_bop_write(0xE1, ((0x00E9 & 0xFF00) | (0x00E9 & 0x00FF)), &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr e1 D0~D7, PAMD TH
+    //XHC, 2011/04/15 update search MR threshold
+//    pkt_size += fm_bop_write(0xE3, FMR_MR_TH, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr e3 1B0
+       //Run,2013/01 smt scan, ignore this
+    pkt_size += fm_bop_write(0xE3, 0x01BD, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr e3 1B0
+    pkt_size += fm_bop_write(0xE4, 0x008F, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr e4 8f
+    pkt_size += fm_bop_write(0xCC, 0x0488, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr cc 488
+    pkt_size += fm_bop_write(0xD6, 0x036A, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr d6 36a
+    pkt_size += fm_bop_write(0xD7, 0x836a, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr d7 836a
+    pkt_size += fm_bop_write(0xDD, 0x0080, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr dd 80
+    pkt_size += fm_bop_write(0xB0, 0xcd00, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr b0 cd00
+    //XHC, 2011/03/18 Update AFC gain[wr 96 41E2->4000][wr 97 049A->021F]
+    //[wr 98 0B66->0D00][wr 99 0E1E->0E7F][wr D0 8233->8192][wr D1 20BC->2086]
+    //[wr 90 03FF->0192][wr 91 01BE->0086][wr 92 03FF->0192][wr 93 0354->0086]
+    //[wr 94 03FF->0192][wr 95 0354->0086][wr 52 17F3]
+    pkt_size += fm_bop_write(0x96, 0x4000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 96     41E2 
+    pkt_size += fm_bop_write(0x97, 0x021F, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 97     049A 
+    pkt_size += fm_bop_write(0x98, 0x0D00, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr  98    0B66 
+    pkt_size += fm_bop_write(0x99, 0x0E7F, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 99     0E1E 
+    pkt_size += fm_bop_write(0xD0, 0x8192, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr D0    8233 
+    pkt_size += fm_bop_write(0xD1, 0x2086, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr D1    20BC 
+    pkt_size += fm_bop_write(0x90, 0x0192, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 90     03ff 
+    pkt_size += fm_bop_write(0x91, 0x0086, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 91     01BE 
+    pkt_size += fm_bop_write(0x92, 0x0192, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 92     03FF 
+    pkt_size += fm_bop_write(0x93, 0x0086, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 93     0354 
+    pkt_size += fm_bop_write(0x94, 0x0192, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 94     03FF 
+    pkt_size += fm_bop_write(0x95, 0x0086, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 95     0354 
+    pkt_size += fm_bop_write(0x52, 0x17F3, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 95     0354 
+    // fm_rgf_fmx
+    pkt_size += fm_bop_write(0x9F, 0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9f 1
+    pkt_size += fm_bop_write(0xDE, 0x3388, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr de 3388
+    pkt_size += fm_bop_write(0xC2, 0x0180, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr c2 180
+    pkt_size += fm_bop_write(0xC3, 0x0180, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr c3 180
+    pkt_size += fm_bop_write(0xDB, 0x0181, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr db 181
+    pkt_size += fm_bop_write(0xDC, 0x0184, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr dc 184
+    pkt_size += fm_bop_write(0xA2, 0x03C0, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a2 3c0
+    pkt_size += fm_bop_write(0xA3, 0x03C0, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a3 3c0
+    pkt_size += fm_bop_write(0xA4, 0x03C0, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a4 3c0
+    pkt_size += fm_bop_write(0xA5, 0x03C0, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a5 3c0
+    pkt_size += fm_bop_write(0xA6, 0x03C0, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a6 3c0
+    pkt_size += fm_bop_write(0xA7, 0x03C0, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a7 3c0
+    pkt_size += fm_bop_write(0xE3, 0x0280, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr e3 280
+    pkt_size += fm_bop_write(0xE4, 0x0280, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr e4 280
+    pkt_size += fm_bop_write(0xE5, 0x0280, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr e5 280
+    pkt_size += fm_bop_write(0xE6, 0x026C, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr e6 26c
+    pkt_size += fm_bop_write(0xE7, 0x026C, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr e7 26c
+    pkt_size += fm_bop_write(0xEA, 0x026C, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr ea 26c
+    pkt_size += fm_bop_udelay(1000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 1000
+    pkt_size += fm_bop_write(0xB6, 0x03FC, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr b6 3fc
+    pkt_size += fm_bop_write(0xB7, 0x02C1, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr b7 2c1
+    pkt_size += fm_bop_write(0xA8, 0x0820, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 820
+    pkt_size += fm_bop_write(0xAC, 0x065E, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr ac 65e
+    pkt_size += fm_bop_write(0xAD, 0x09AD, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr ad 9ad
+    pkt_size += fm_bop_write(0xAE, 0x0CF8, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr ae cf8
+    pkt_size += fm_bop_write(0xAF, 0x0302, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr af 302
+    pkt_size += fm_bop_write(0xB0, 0x04A6, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr b0 4a6
+    pkt_size += fm_bop_write(0xB1, 0x062C, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr b1 62c
+    pkt_size += fm_bop_write(0xEC, 0x014A, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr ec 14a
+    pkt_size += fm_bop_write(0xC8, 0x0232, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr c8 232
+    pkt_size += fm_bop_write(0xC7, 0x0184, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr c7 0184
+    pkt_size += fm_bop_write(0xD8, 0x00E8, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr d8 0e8
+    pkt_size += fm_bop_write(0xFB, 0x051F, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr fb 51f
+    pkt_size += fm_bop_udelay(1000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 1000
+    //XHC,2011/03/18 [wr C9 01F0][wr CA 0250][wr D4 2657]
+    pkt_size += fm_bop_write(0xC9, 0x01F0, &tx_buf[pkt_size], tx_buf_size - pkt_size);
+    pkt_size += fm_bop_write(0xCA, 0x0250, &tx_buf[pkt_size], tx_buf_size - pkt_size);
+    pkt_size += fm_bop_write(0xD4, 0x2657, &tx_buf[pkt_size], tx_buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x9F, 0x0002, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9f 2
+    pkt_size += fm_bop_write(0xA8, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 0
+    pkt_size += fm_bop_write(0xA8, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 0
+    pkt_size += fm_bop_write(0xA8, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 0
+    pkt_size += fm_bop_write(0xA8, 0xFF80, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 ff80
+    pkt_size += fm_bop_write(0xA8, 0x0061, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 61
+    pkt_size += fm_bop_write(0xA8, 0xFF22, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 ff22
+    pkt_size += fm_bop_write(0xA8, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 0
+    pkt_size += fm_bop_write(0xA8, 0x0100, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 100
+    pkt_size += fm_bop_write(0xA8, 0x009A, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 9a
+    pkt_size += fm_bop_write(0xA8, 0xFF80, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 ff80
+    pkt_size += fm_bop_write(0xA8, 0x0140, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 140    
+    pkt_size += fm_bop_write(0xA8, 0xFF42, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 ff42   
+    pkt_size += fm_bop_write(0xA8, 0xFFE0, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 ffe0    
+    pkt_size += fm_bop_write(0xA8, 0x0114, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 114    
+    pkt_size += fm_bop_write(0xA8, 0xFF4E, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 ff4e   
+    pkt_size += fm_bop_write(0xA8, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 0
+    pkt_size += fm_bop_write(0xA8, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 0
+    pkt_size += fm_bop_write(0xA8, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 0
+    pkt_size += fm_bop_write(0xA8, 0x003E, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 3e
+    pkt_size += fm_bop_write(0xA8, 0xFF6E, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 ff6e
+    pkt_size += fm_bop_write(0xA8, 0x0087, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 87
+    pkt_size += fm_bop_write(0xA8, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 0
+    pkt_size += fm_bop_write(0xA8, 0xFEDC, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 fedc
+    pkt_size += fm_bop_write(0xA8, 0x0015, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 15
+    pkt_size += fm_bop_write(0xA8, 0x00CF, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 cf
+    pkt_size += fm_bop_write(0xA8, 0xFF6B, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 ff6b
+    pkt_size += fm_bop_write(0xA8, 0x0164, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 164
+    pkt_size += fm_bop_write(0xA8, 0x002B, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 2b
+    pkt_size += fm_bop_write(0xA8, 0xFF7E, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 ff7e
+    pkt_size += fm_bop_write(0xA8, 0x0065, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a8 65
+    pkt_size += fm_bop_udelay(10000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 10000
+    pkt_size += fm_bop_write(0x9F, 0x0002, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9f 2
+    pkt_size += fm_bop_write(0xA9, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a9 0
+    pkt_size += fm_bop_write(0xA9, 0xFFEE, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a9 ffee
+    pkt_size += fm_bop_write(0xA9, 0xFF81, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a9 ff81
+    //XHC,2011/03/18 [wr A9 FFC3]
+    pkt_size += fm_bop_write(0xA9, 0xFFC3, &tx_buf[pkt_size], tx_buf_size - pkt_size);
+    pkt_size += fm_bop_write(0xA9, 0x0022, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a9 22
+    pkt_size += fm_bop_write(0xA9, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a9 0
+    pkt_size += fm_bop_write(0xA9, 0xFFCC, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a9 ffcc
+    pkt_size += fm_bop_write(0xA9, 0x0023, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a9 23
+    pkt_size += fm_bop_write(0xA9, 0xFFDA, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a9 ffda
+    pkt_size += fm_bop_write(0xA9, 0xFFF7, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a9 fff7
+    pkt_size += fm_bop_udelay(10, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 10
+    pkt_size += fm_bop_write(0x9F, 0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9f 1
+    pkt_size += fm_bop_write(0xD3, 0x250b, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr d3 250b
+    pkt_size += fm_bop_write(0xBB, 0x2320, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr bb 2320
+    pkt_size += fm_bop_write(0xD0, 0x02f8, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr d0 02f8
+    pkt_size += fm_bop_write(0xEC, 0x019a, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr ec 19a
+    pkt_size += fm_bop_write(0xFE, 0x2140, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr fe 2140
+    pkt_size += fm_bop_write(0x9F, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9f 0
+    // fm_rgf_rds    
+    pkt_size += fm_bop_write(0x9F, 0x0003, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9f 3
+    pkt_size += fm_bop_write(0xBD, 0x37EB, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr bd 37eb
+    pkt_size += fm_bop_write(0xBC, 0x0404, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr bc 404
+    pkt_size += fm_bop_write(0x9F, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9f 0
+
+    tx_buf[2] = (fm_u8)((pkt_size-4) & 0x00FF);
+    tx_buf[3] = (fm_u8)(((pkt_size-4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+/*
+ * mt6620_pwrup_digital_init - Wholechip FM Power Up: step 4, FM Digital Init: fm_rgf_maincon
+ * @buf - target buf
+ * @buf_size - buffer size
+ * return package size
+ */
+fm_s32 mt6620_pwrup_digital_init_1(fm_u8 *buf, fm_s32 buf_size)
+{
+    fm_s32 pkt_size = 0;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_ENABLE_OPCODE;
+    pkt_size = 4;
+
+
+    // fm_rgf_maincon
+    //rd 62
+    pkt_size += fm_bop_write(0x65, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 65 0
+    pkt_size += fm_bop_write(0x64, 0x0001, &buf[pkt_size], buf_size - pkt_size);//wr 64 1
+    pkt_size += fm_bop_write(0x63, 0x0480, &buf[pkt_size], buf_size - pkt_size);//wr 63 480
+    pkt_size += fm_bop_write(0x6D, 0x1AB2, &buf[pkt_size], buf_size - pkt_size);//wr 6d 1ab2
+    pkt_size += fm_bop_write(0x6B, 0x2100, &buf[pkt_size], buf_size - pkt_size);//wr 6b 2100
+    pkt_size += fm_bop_write(0x68, 0xE100, &buf[pkt_size], buf_size - pkt_size);//wr 68 E100
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+fm_s32 mt6620_pwrup_digital_init_2(fm_u8 *buf, fm_s32 buf_size)
+{
+    fm_s32 pkt_size = 0;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_ENABLE_OPCODE;
+    pkt_size = 4;
+
+    pkt_size += fm_bop_write(0x68, 0xE000, &buf[pkt_size], buf_size - pkt_size);//wr 68 E000
+    // fm_rgf_dac
+    pkt_size += fm_bop_write(0x9C, 0xab48, &buf[pkt_size], buf_size - pkt_size);//wr 9c ab48
+    pkt_size += fm_bop_write(0x9E, 0x000C, &buf[pkt_size], buf_size - pkt_size);//wr 9e c
+    pkt_size += fm_bop_write(0x71, 0x807f, &buf[pkt_size], buf_size - pkt_size);//wr 71 807f
+    pkt_size += fm_bop_write(0x72, 0x878f, &buf[pkt_size], buf_size - pkt_size);//wr 72 878f
+    //XHC, 2011/04/29 update 0x73 form 0x07C3 to 0x07C1 speed up I/Q calibration
+    pkt_size += fm_bop_write(0x73, 0x07c1, &buf[pkt_size], buf_size - pkt_size);//wr 73 7c3
+    // fm_rgf_front
+    pkt_size += fm_bop_write(0x9F, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 9f 0
+    pkt_size += fm_bop_write(0xCB, 0x00B0, &buf[pkt_size], buf_size - pkt_size);//wr cb b0
+    //XHC, 2011/05/06 FM RSSI config
+    pkt_size += fm_bop_write(0xE0, ((0xA301 & 0xFC00) | (FMR_RSSI_TH_LONG_MT6620 & 0x03FF)), &buf[pkt_size], buf_size - pkt_size);//wr e0 a301
+    pkt_size += fm_bop_write(0xE1, ((0x00E9 & 0xFF00) | (FMR_CQI_TH_MT6620 & 0x00FF)), &buf[pkt_size], buf_size - pkt_size);//wr e1 D0~D7, PAMD TH
+    //XHC, 2011/04/15 update search MR threshold
+    pkt_size += fm_bop_write(0xE3, FMR_MR_TH_MT6620, &buf[pkt_size], buf_size - pkt_size);//wr e3 1B0
+    pkt_size += fm_bop_write(0xE4, 0x008F, &buf[pkt_size], buf_size - pkt_size);//wr e4 8f
+    pkt_size += fm_bop_write(0xCC, 0x0488, &buf[pkt_size], buf_size - pkt_size);//wr cc 488
+    pkt_size += fm_bop_write(0xD6, 0x036A, &buf[pkt_size], buf_size - pkt_size);//wr d6 36a
+    pkt_size += fm_bop_write(0xD7, 0x836a, &buf[pkt_size], buf_size - pkt_size);//wr d7 836a
+    pkt_size += fm_bop_write(0xDD, 0x0080, &buf[pkt_size], buf_size - pkt_size);//wr dd 80
+    pkt_size += fm_bop_write(0xB0, 0xcd00, &buf[pkt_size], buf_size - pkt_size);//wr b0 cd00
+    //XHC, 2011/03/18 Update AFC gain[wr 96 41E2->4000][wr 97 049A->021F]
+    //[wr 98 0B66->0D00][wr 99 0E1E->0E7F][wr D0 8233->8192][wr D1 20BC->2086]
+    //[wr 90 03FF->0192][wr 91 01BE->0086][wr 92 03FF->0192][wr 93 0354->0086]
+    //[wr 94 03FF->0192][wr 95 0354->0086][wr 52 17F3]
+    pkt_size += fm_bop_write(0x96, 0x4000, &buf[pkt_size], buf_size - pkt_size);//wr 96     41E2
+    pkt_size += fm_bop_write(0x97, 0x021F, &buf[pkt_size], buf_size - pkt_size);//wr 97     049A
+    pkt_size += fm_bop_write(0x98, 0x0D00, &buf[pkt_size], buf_size - pkt_size);//wr  98    0B66
+    pkt_size += fm_bop_write(0x99, 0x0E7F, &buf[pkt_size], buf_size - pkt_size);//wr 99     0E1E
+    pkt_size += fm_bop_write(0xD0, 0x8192, &buf[pkt_size], buf_size - pkt_size);//wr D0    8233
+    pkt_size += fm_bop_write(0xD1, 0x2086, &buf[pkt_size], buf_size - pkt_size);//wr D1    20BC
+    pkt_size += fm_bop_write(0x90, 0x0192, &buf[pkt_size], buf_size - pkt_size);//wr 90     03ff
+    pkt_size += fm_bop_write(0x91, 0x0086, &buf[pkt_size], buf_size - pkt_size);//wr 91     01BE
+    pkt_size += fm_bop_write(0x92, 0x0192, &buf[pkt_size], buf_size - pkt_size);//wr 92     03FF
+    pkt_size += fm_bop_write(0x93, 0x0086, &buf[pkt_size], buf_size - pkt_size);//wr 93     0354
+    pkt_size += fm_bop_write(0x94, 0x0192, &buf[pkt_size], buf_size - pkt_size);//wr 94     03FF
+    pkt_size += fm_bop_write(0x95, 0x0086, &buf[pkt_size], buf_size - pkt_size);//wr 95     0354
+    pkt_size += fm_bop_write(0x52, 0x17F3, &buf[pkt_size], buf_size - pkt_size);//wr 95     0354
+    // fm_rgf_fmx
+    pkt_size += fm_bop_write(0x9F, 0x0001, &buf[pkt_size], buf_size - pkt_size);//wr 9f 1
+    pkt_size += fm_bop_write(0xDE, 0x3388, &buf[pkt_size], buf_size - pkt_size);//wr de 3388
+    pkt_size += fm_bop_write(0xC2, 0x0180, &buf[pkt_size], buf_size - pkt_size);//wr c2 180
+    pkt_size += fm_bop_write(0xC3, 0x0180, &buf[pkt_size], buf_size - pkt_size);//wr c3 180
+    pkt_size += fm_bop_write(0xDB, 0x0181, &buf[pkt_size], buf_size - pkt_size);//wr db 181
+    pkt_size += fm_bop_write(0xDC, 0x0184, &buf[pkt_size], buf_size - pkt_size);//wr dc 184
+    pkt_size += fm_bop_write(0xA2, 0x03C0, &buf[pkt_size], buf_size - pkt_size);//wr a2 3c0
+    pkt_size += fm_bop_write(0xA3, 0x03C0, &buf[pkt_size], buf_size - pkt_size);//wr a3 3c0
+    pkt_size += fm_bop_write(0xA4, 0x03C0, &buf[pkt_size], buf_size - pkt_size);//wr a4 3c0
+    pkt_size += fm_bop_write(0xA5, 0x03C0, &buf[pkt_size], buf_size - pkt_size);//wr a5 3c0
+    pkt_size += fm_bop_write(0xA6, 0x03C0, &buf[pkt_size], buf_size - pkt_size);//wr a6 3c0
+    pkt_size += fm_bop_write(0xA7, 0x03C0, &buf[pkt_size], buf_size - pkt_size);//wr a7 3c0
+    pkt_size += fm_bop_write(0xE3, 0x0280, &buf[pkt_size], buf_size - pkt_size);//wr e3 280
+    pkt_size += fm_bop_write(0xE4, 0x0280, &buf[pkt_size], buf_size - pkt_size);//wr e4 280
+    pkt_size += fm_bop_write(0xE5, 0x0280, &buf[pkt_size], buf_size - pkt_size);//wr e5 280
+    pkt_size += fm_bop_write(0xE6, 0x026C, &buf[pkt_size], buf_size - pkt_size);//wr e6 26c
+    pkt_size += fm_bop_write(0xE7, 0x026C, &buf[pkt_size], buf_size - pkt_size);//wr e7 26c
+    pkt_size += fm_bop_write(0xEA, 0x026C, &buf[pkt_size], buf_size - pkt_size);//wr ea 26c
+    pkt_size += fm_bop_udelay(1000, &buf[pkt_size], buf_size - pkt_size);//delay 1000
+    pkt_size += fm_bop_write(0xB6, 0x03FC, &buf[pkt_size], buf_size - pkt_size);//wr b6 3fc
+    pkt_size += fm_bop_write(0xB7, 0x02C1, &buf[pkt_size], buf_size - pkt_size);//wr b7 2c1
+    pkt_size += fm_bop_write(0xA8, 0x0820, &buf[pkt_size], buf_size - pkt_size);//wr a8 820
+    pkt_size += fm_bop_write(0xAC, 0x065E, &buf[pkt_size], buf_size - pkt_size);//wr ac 65e
+    pkt_size += fm_bop_write(0xAD, 0x09AD, &buf[pkt_size], buf_size - pkt_size);//wr ad 9ad
+    pkt_size += fm_bop_write(0xAE, 0x0CF8, &buf[pkt_size], buf_size - pkt_size);//wr ae cf8
+    pkt_size += fm_bop_write(0xAF, 0x0302, &buf[pkt_size], buf_size - pkt_size);//wr af 302
+    pkt_size += fm_bop_write(0xB0, 0x04A6, &buf[pkt_size], buf_size - pkt_size);//wr b0 4a6
+    pkt_size += fm_bop_write(0xB1, 0x062C, &buf[pkt_size], buf_size - pkt_size);//wr b1 62c
+    pkt_size += fm_bop_write(0xEC, 0x014A, &buf[pkt_size], buf_size - pkt_size);//wr ec 14a
+    pkt_size += fm_bop_write(0xC8, 0x0232, &buf[pkt_size], buf_size - pkt_size);//wr c8 232
+    pkt_size += fm_bop_write(0xC7, 0x0184, &buf[pkt_size], buf_size - pkt_size);//wr c7 0184
+    pkt_size += fm_bop_write(0xD8, 0x00E8, &buf[pkt_size], buf_size - pkt_size);//wr d8 0e8
+    pkt_size += fm_bop_write(0xFB, 0x051F, &buf[pkt_size], buf_size - pkt_size);//wr fb 51f
+    pkt_size += fm_bop_udelay(1000, &buf[pkt_size], buf_size - pkt_size);//delay 1000
+    //XHC,2011/03/18 [wr C9 01F0][wr CA 0250][wr D4 2657]
+    pkt_size += fm_bop_write(0xC9, 0x01F0, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0xCA, 0x0250, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0xD4, 0x2657, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x9F, 0x0002, &buf[pkt_size], buf_size - pkt_size);//wr 9f 2
+    pkt_size += fm_bop_write(0xA8, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr a8 0
+    pkt_size += fm_bop_write(0xA8, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr a8 0
+    pkt_size += fm_bop_write(0xA8, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr a8 0
+    pkt_size += fm_bop_write(0xA8, 0xFF80, &buf[pkt_size], buf_size - pkt_size);//wr a8 ff80
+    pkt_size += fm_bop_write(0xA8, 0x0061, &buf[pkt_size], buf_size - pkt_size);//wr a8 61
+    pkt_size += fm_bop_write(0xA8, 0xFF22, &buf[pkt_size], buf_size - pkt_size);//wr a8 ff22
+    pkt_size += fm_bop_write(0xA8, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr a8 0
+    pkt_size += fm_bop_write(0xA8, 0x0100, &buf[pkt_size], buf_size - pkt_size);//wr a8 100
+    pkt_size += fm_bop_write(0xA8, 0x009A, &buf[pkt_size], buf_size - pkt_size);//wr a8 9a
+    pkt_size += fm_bop_write(0xA8, 0xFF80, &buf[pkt_size], buf_size - pkt_size);//wr a8 ff80
+    pkt_size += fm_bop_write(0xA8, 0x0140, &buf[pkt_size], buf_size - pkt_size);//wr a8 140
+    pkt_size += fm_bop_write(0xA8, 0xFF42, &buf[pkt_size], buf_size - pkt_size);//wr a8 ff42
+    pkt_size += fm_bop_write(0xA8, 0xFFE0, &buf[pkt_size], buf_size - pkt_size);//wr a8 ffe0
+    pkt_size += fm_bop_write(0xA8, 0x0114, &buf[pkt_size], buf_size - pkt_size);//wr a8 114
+    pkt_size += fm_bop_write(0xA8, 0xFF4E, &buf[pkt_size], buf_size - pkt_size);//wr a8 ff4e
+    pkt_size += fm_bop_write(0xA8, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr a8 0
+    pkt_size += fm_bop_write(0xA8, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr a8 0
+    pkt_size += fm_bop_write(0xA8, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr a8 0
+    pkt_size += fm_bop_write(0xA8, 0x003E, &buf[pkt_size], buf_size - pkt_size);//wr a8 3e
+    pkt_size += fm_bop_write(0xA8, 0xFF6E, &buf[pkt_size], buf_size - pkt_size);//wr a8 ff6e
+    pkt_size += fm_bop_write(0xA8, 0x0087, &buf[pkt_size], buf_size - pkt_size);//wr a8 87
+    pkt_size += fm_bop_write(0xA8, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr a8 0
+    pkt_size += fm_bop_write(0xA8, 0xFEDC, &buf[pkt_size], buf_size - pkt_size);//wr a8 fedc
+    pkt_size += fm_bop_write(0xA8, 0x0015, &buf[pkt_size], buf_size - pkt_size);//wr a8 15
+    pkt_size += fm_bop_write(0xA8, 0x00CF, &buf[pkt_size], buf_size - pkt_size);//wr a8 cf
+    pkt_size += fm_bop_write(0xA8, 0xFF6B, &buf[pkt_size], buf_size - pkt_size);//wr a8 ff6b
+    pkt_size += fm_bop_write(0xA8, 0x0164, &buf[pkt_size], buf_size - pkt_size);//wr a8 164
+    pkt_size += fm_bop_write(0xA8, 0x002B, &buf[pkt_size], buf_size - pkt_size);//wr a8 2b
+    pkt_size += fm_bop_write(0xA8, 0xFF7E, &buf[pkt_size], buf_size - pkt_size);//wr a8 ff7e
+    pkt_size += fm_bop_write(0xA8, 0x0065, &buf[pkt_size], buf_size - pkt_size);//wr a8 65
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+fm_s32 mt6620_pwrup_digital_init_3(fm_u8 *buf, fm_s32 buf_size)
+{
+    fm_s32 pkt_size = 0;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_ENABLE_OPCODE;
+    pkt_size = 4;
+
+    pkt_size += fm_bop_write(0x9F, 0x0002, &buf[pkt_size], buf_size - pkt_size);//wr 9f 2
+    pkt_size += fm_bop_write(0xA9, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr a9 0
+    pkt_size += fm_bop_write(0xA9, 0xFFEE, &buf[pkt_size], buf_size - pkt_size);//wr a9 ffee
+    pkt_size += fm_bop_write(0xA9, 0xFF81, &buf[pkt_size], buf_size - pkt_size);//wr a9 ff81
+    //XHC,2011/03/18 [wr A9 FFC3]
+    pkt_size += fm_bop_write(0xA9, 0xFFC3, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0xA9, 0x0022, &buf[pkt_size], buf_size - pkt_size);//wr a9 22
+    pkt_size += fm_bop_write(0xA9, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr a9 0
+    pkt_size += fm_bop_write(0xA9, 0xFFCC, &buf[pkt_size], buf_size - pkt_size);//wr a9 ffcc
+    pkt_size += fm_bop_write(0xA9, 0x0023, &buf[pkt_size], buf_size - pkt_size);//wr a9 23
+    pkt_size += fm_bop_write(0xA9, 0xFFDA, &buf[pkt_size], buf_size - pkt_size);//wr a9 ffda
+    pkt_size += fm_bop_write(0xA9, 0xFFF7, &buf[pkt_size], buf_size - pkt_size);//wr a9 fff7
+    pkt_size += fm_bop_udelay(10, &buf[pkt_size], buf_size - pkt_size);//delay 10
+    pkt_size += fm_bop_write(0x9F, 0x0001, &buf[pkt_size], buf_size - pkt_size);//wr 9f 1
+    pkt_size += fm_bop_write(0xD3, 0x250b, &buf[pkt_size], buf_size - pkt_size);//wr d3 250b
+    pkt_size += fm_bop_write(0xBB, 0x2320, &buf[pkt_size], buf_size - pkt_size);//wr bb 2320
+    pkt_size += fm_bop_write(0xD0, 0x02f8, &buf[pkt_size], buf_size - pkt_size);//wr d0 02f8
+    pkt_size += fm_bop_write(0xEC, 0x019a, &buf[pkt_size], buf_size - pkt_size);//wr ec 19a
+    pkt_size += fm_bop_write(0xFE, 0x2140, &buf[pkt_size], buf_size - pkt_size);//wr fe 2140
+    pkt_size += fm_bop_write(0x9F, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 9f 0
+    // fm_rgf_rds
+    pkt_size += fm_bop_write(0x9F, 0x0003, &buf[pkt_size], buf_size - pkt_size);//wr 9f 3
+    pkt_size += fm_bop_write(0xBD, 0x37EB, &buf[pkt_size], buf_size - pkt_size);//wr bd 37eb
+    pkt_size += fm_bop_write(0xBC, 0x0404, &buf[pkt_size], buf_size - pkt_size);//wr bc 808
+    pkt_size += fm_bop_write(0x9F, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 9f 0
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+/*
+ * mt6620_pwrdown - Wholechip FM Power down: Digital Modem Power Down
+ * @buf - target buf
+ * @buf_size - buffer size
+ * return package size
+ */
+fm_s32 mt6620_pwrdown(fm_u8 *buf, fm_s32 buf_size)
+{
+    fm_s32 pkt_size = 0;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_ENABLE_OPCODE;
+    pkt_size = 4;
+
+    //Digital Modem Power Down
+    pkt_size += fm_bop_write(0x63, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 63 0
+    pkt_size += fm_bop_modify(0x6E, 0xFFFC, 0x0000, &buf[pkt_size], buf_size - pkt_size);// clear 0x6e[1:0], round1
+    pkt_size += fm_bop_modify(0x6E, 0xFFFC, 0x0000, &buf[pkt_size], buf_size - pkt_size);// clear 0x6e[1:0], round2
+    pkt_size += fm_bop_modify(0x6E, 0xFFFC, 0x0000, &buf[pkt_size], buf_size - pkt_size);// clear 0x6e[1:0], round3
+    pkt_size += fm_bop_modify(0x6E, 0xFFFC, 0x0000, &buf[pkt_size], buf_size - pkt_size);// clear 0x6e[1:0], round4
+    //ADPLL Power Off Sequence
+    pkt_size += fm_bop_write(0x2A, 0x0022, &buf[pkt_size], buf_size - pkt_size);//wr 2a 22
+    pkt_size += fm_bop_write(0x1E, 0x0860, &buf[pkt_size], buf_size - pkt_size);//wr 1E 0860
+    pkt_size += fm_bop_write(0x20, 0x0720, &buf[pkt_size], buf_size - pkt_size);//wr 20 0720
+    pkt_size += fm_bop_write(0x20, 0x2720, &buf[pkt_size], buf_size - pkt_size);//wr 20 2720
+    //ANALOG/RF Power Off Sequence
+    pkt_size += fm_bop_write(0x00, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 0 0
+    pkt_size += fm_bop_write(0x01, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 1 0
+    pkt_size += fm_bop_write(0x04, 0x0141, &buf[pkt_size], buf_size - pkt_size);//wr 4 0141
+    pkt_size += fm_bop_write(0x09, 0x0964, &buf[pkt_size], buf_size - pkt_size);//wr 9 0964
+    pkt_size += fm_bop_write(0x0C, 0x288C, &buf[pkt_size], buf_size - pkt_size);//wr c 288c
+    pkt_size += fm_bop_write(0x26, 0x0004, &buf[pkt_size], buf_size - pkt_size);//wr 26 0004
+    pkt_size += fm_bop_write(0x3A, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 3A 0000
+    pkt_size += fm_bop_write(0x3B, 0x00C3, &buf[pkt_size], buf_size - pkt_size);//wr 3B 00C3
+    pkt_size += fm_bop_write(0x3E, 0x3280, &buf[pkt_size], buf_size - pkt_size);//wr 3E 3280
+    pkt_size += fm_bop_write(0x3F, 0x4E16, &buf[pkt_size], buf_size - pkt_size);//wr 3F 4E16
+    pkt_size += fm_bop_write(0x41, 0x0004, &buf[pkt_size], buf_size - pkt_size);//wr 41 0004
+    //clear TX settings
+    pkt_size += fm_bop_write(0x12, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 12 0000
+    pkt_size += fm_bop_write(0x47, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 47 0000
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+/*
+ * mt6620_rampdown - f/w will wait for STC_DONE interrupt
+ * @buf - target buf
+ * @buf_size - buffer size
+ * return package size
+ */
+fm_s32 mt6620_rampdown(fm_u8 *buf, fm_s32 buf_size)
+{
+    fm_s32 pkt_size = 0;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_RAMPDOWN_OPCODE;
+    pkt_size = 4;
+
+    pkt_size += fm_bop_modify(0x9C, 0xFF87, 0x0068, &buf[pkt_size], buf_size - pkt_size);//wr 9c[3] = 1, ramp down
+    pkt_size += fm_bop_write(0x9F, 0x0001, &buf[pkt_size], buf_size - pkt_size);//wr 9f 1
+    pkt_size += fm_bop_write(0xC8, 0x0101, &buf[pkt_size], buf_size - pkt_size);//wr c8 101
+    pkt_size += fm_bop_write(0xDD, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr dd 0
+    pkt_size += fm_bop_write(0xD8, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr d8 0
+    pkt_size += fm_bop_write(0x9F, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 9f 0
+    pkt_size += fm_bop_udelay(35000, &buf[pkt_size], buf_size - pkt_size);//delay 35000
+    //disable interrupt before rampdown
+    pkt_size += fm_bop_write(0x6B, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 6b 0000
+    pkt_size += fm_bop_modify(0x63, 0xFFF0, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 63[3:0] = 0, ramp down
+    pkt_size += fm_bop_rd_until(0x6f, 0x0001, 0x0000, &buf[pkt_size], buf_size - pkt_size);//Poll 6f[0] = b'0
+    pkt_size += fm_bop_write(0x6B, 0x2100, &buf[pkt_size], buf_size - pkt_size);//wr 6b 2100
+    //enable interrupt after rampdown
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+#if 0//ramp down tx will do in tx tune  flow
+fm_s32 mt6620_rampdown_tx(fm_u8 *tx_buf, fm_s32 tx_buf_size)
+{
+    fm_s32 pkt_size = 0;
+
+    if(tx_buf_size < TX_BUF_SIZE){
+        return (-1);
+    }
+    
+    tx_buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    tx_buf[1] = FM_RAMPDOWN_OPCODE;
+    pkt_size = 4;
+
+    pkt_size += fm_bop_write(0x3B, 0x0500, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 3b 0500
+    pkt_size += fm_bop_write(0x3A, 0x00FF, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 3a ff
+    pkt_size += fm_bop_write(0x65, 0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 65 1
+    pkt_size += fm_bop_write(0x48, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 48 0
+    
+    tx_buf[2] = (fm_u8)((pkt_size-4) & 0x00FF);
+    tx_buf[3] = (fm_u8)(((pkt_size-4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+#endif
+/*
+ * mt6620_tune - execute tune action,
+ * @buf - target buf
+ * @buf_size - buffer size
+ * @freq - 760 ~ 1080, 100KHz unit
+ * return package size
+ */
+fm_s32 mt6620_tune_1(fm_u8 *buf, fm_s32 buf_size, fm_u16 freq)
+{
+    fm_s32 pkt_size = 0;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+    if (0 == fm_get_channel_space(freq)) {
+        freq *= 10;
+    }
+
+    freq = (freq - 6400) * 2 /10;
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_TUNE_OPCODE;
+    pkt_size = 4;
+
+    pkt_size += fm_bop_modify(0x0F, 0xFC00, freq, &buf[pkt_size], buf_size - pkt_size);// set 0x0F[9:0] = 0x029e, => ((97.5 - 64) * 20)
+    pkt_size += fm_bop_modify(0x63, 0xFFFF, 0x0001, &buf[pkt_size], buf_size - pkt_size);// set 0x63[0] = 1
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+fm_s32 mt6620_tune_2(fm_u8 *buf, fm_s32 buf_size, fm_u16 freq)
+{
+    fm_s32 pkt_size = 0;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+/*    
+    if (0 == fm_get_channel_space(freq)) {
+        freq *= 10;
+    }
+
+    freq = (freq - 640) * 2 / 10;
+*/
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_TUNE_OPCODE;
+    pkt_size = 4;
+
+    pkt_size += fm_bop_modify(0x9C, 0xFFF7, 0x0000, &buf[pkt_size], buf_size - pkt_size);// set 0x9C[3] = 0
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+fm_s32 mt6620_tune_3(fm_u8 *buf, fm_s32 buf_size, fm_u16 freq)
+{
+    fm_s32 pkt_size = 0;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+/*    
+    if (0 == fm_get_channel_space(freq)) {
+        freq *= 10;
+    }
+
+    freq = (freq - 640) * 2 / 10;
+*/
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_TUNE_OPCODE;
+    pkt_size = 4;
+
+    pkt_size += fm_bop_write(0x9F, 0x0001, &buf[pkt_size], buf_size - pkt_size);//wr 9F 1
+    pkt_size += fm_bop_write(0xC8, 0x0232, &buf[pkt_size], buf_size - pkt_size);//wr C8 232
+    pkt_size += fm_bop_write(0xDD, 0x8833, &buf[pkt_size], buf_size - pkt_size);//wr DD 8833
+    pkt_size += fm_bop_write(0xD8, 0x00E8, &buf[pkt_size], buf_size - pkt_size);//wr D8 E8
+    pkt_size += fm_bop_write(0x9F, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 9F 0
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+fm_s32 mt6620_fast_tune(fm_u8 *tx_buf, fm_s32 tx_buf_size, fm_u16 freq)
+{
+    fm_s32 pkt_size = 0;
+
+    if(tx_buf_size < TX_BUF_SIZE){
+        return (-1);
+    }
+    
+    if (0 == fm_get_channel_space(freq)) {
+        freq *= 10;
+    }
+
+    freq = (freq - 6400) * 2 / 10;
+
+    tx_buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    tx_buf[1] = FM_TUNE_OPCODE;
+    pkt_size = 4;
+    
+    pkt_size += fm_bop_modify(0x63, 0xFFF0, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);// set 0x63[3:0] = 0
+    pkt_size += fm_bop_modify(0x6F, 0xFFFE, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);// set 0x6F[0] = 0
+    pkt_size += fm_bop_modify(0x0F, 0xFC00, freq, &tx_buf[pkt_size], tx_buf_size - pkt_size);// set 0x0F[9:0] = 0x029e, => ((97.5 - 64) * 20)
+    //disable interrupt before rampdown
+    pkt_size += fm_bop_write(0x6B, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 6b 0000
+    pkt_size += fm_bop_modify(0x63, 0xFFFE, 0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);// set 0x63[0] = 1
+    pkt_size += fm_bop_rd_until(0x69, 0x0001, 0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);//Poll 69[0] = b'1
+    pkt_size += fm_bop_modify(0x69, 0xFFFE, 0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);// set 0x69[0] = 1
+    pkt_size += fm_bop_write(0x6B, 0x2100, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 6b 2100
+    //enable interrupt after rampdown
+    
+    tx_buf[2] = (fm_u8)((pkt_size-4) & 0x00FF);
+    tx_buf[3] = (fm_u8)(((pkt_size-4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+/*
+ * mt6620_full_cqi_req - execute request cqi info action,
+ * @buf - target buf
+ * @buf_size - buffer size
+ * @freq - 7600 ~ 10800, freq array
+ * @cnt - channel count
+ * @type - request type, 1: a single channel; 2: multi channel; 3:multi channel with 100Khz step; 4: multi channel with 50Khz step
+ * 
+ * return package size
+ */
+
+fm_s32 mt6620_full_cqi_req(fm_u8 *buf, fm_s32 buf_size, fm_u16 freq, fm_s32 cnt, fm_s32 type)
+{
+    fm_s32 pkt_size = 0;
+
+    if(buf_size < TX_BUF_SIZE)
+    {
+        return (-1);
+    }
+    if (0 == fm_get_channel_space(freq))
+    {
+        freq *= 10;
+    }
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_SOFT_MUTE_TUNE_OPCODE;
+    pkt_size = 4;
+
+    switch (type) {
+        case 1:
+            buf[pkt_size] = 0x0001;
+            pkt_size++;
+            buf[pkt_size] = (fm_u8)(freq & 0x00FF);
+            pkt_size++;
+            buf[pkt_size] = (fm_u8)((freq >> 8) & 0x00FF);
+            pkt_size++;
+            break;
+        default:
+            buf[pkt_size] = (fm_u16)type;
+            pkt_size++;
+            break;
+    }
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+
+    return pkt_size;
+       
+}
+
+// freq: 760 ~ 1080, 100KHz unit
+fm_s32 mt6620_tune_tx(fm_u8 *tx_buf, fm_s32 tx_buf_size, fm_u16 freq)
+{
+    fm_s32 pkt_size = 0;
+
+    if(tx_buf_size < TX_BUF_SIZE){
+        return (-1);
+    }
+    
+    if (0 == fm_get_channel_space(freq)) {
+        freq *= 10;
+    }
+
+    freq = (freq - 6400) * 2 / 10;
+
+    tx_buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    tx_buf[1] = FM_TUNE_OPCODE;
+    pkt_size = 4;
+    
+    //XHC, 2011/04/20, ramp down before tune
+    pkt_size += fm_bop_write(0x3B, 0x0500, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 3b 0500
+    pkt_size += fm_bop_write(0x3A, 0x00FF, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 3a ff
+    pkt_size += fm_bop_write(0x65, 0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 65 1
+    pkt_size += fm_bop_write(0x48, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 48 0
+    //XHC, 2011/04/14
+    pkt_size += fm_bop_modify(0x41, 0xFFFE, 0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);// set 0x41[0] = 1
+    //XHC, 2011/04/18
+    pkt_size += fm_bop_modify(0x12, 0x7FFF, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);// set 0x12[15] = 0
+    //XHC, 2011/04/22, clear RTC compensation info
+    pkt_size += fm_bop_modify(0x47, 0x003F, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);// set 0x47[15:6] = 0
+    pkt_size += fm_bop_modify(0x0F, 0xFC00, freq, &tx_buf[pkt_size], tx_buf_size - pkt_size);// set 0x0F[9:0] = freq
+    pkt_size += fm_bop_write(0x26, 0x002C, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 26 002C --> SCAL Related --> SCAL_EN and SCAL_GM_EN
+    pkt_size += fm_bop_udelay(1000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 1000us
+    pkt_size += fm_bop_write(0x26, 0x003C, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 26 003C --> SCAL_BUF_EN
+    pkt_size += fm_bop_udelay(1000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 1000us
+    pkt_size += fm_bop_write(0x10, 0x1E8D, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 10 1e8d
+    pkt_size += fm_bop_udelay(1000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 1000us
+    pkt_size += fm_bop_write(0x10, 0x9E8D, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 10 9e8d
+    pkt_size += fm_bop_udelay(10000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 10000us
+    pkt_size += fm_bop_write(0x26, 0x0024, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 26 0024 --> Turn off SCAL gm and BUF
+    pkt_size += fm_bop_write(0x65, 0x400F, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 65 400f
+    pkt_size += fm_bop_write(0x48, 0x8000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 48 8000
+    pkt_size += fm_bop_write(0x3B, 0x0420, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 3b 0420
+    pkt_size += fm_bop_write(0x3A, 0x01FF, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 3a 1ff
+    //XHC, 2011/04/14
+    //pkt_size += fm_bop_udelay(10000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 10000us
+    //pkt_size += fm_bop_modify(0x41, 0xFFFE, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);// set 0x41[0] = 0
+    
+    tx_buf[2] = (fm_u8)((pkt_size-4) & 0x00FF);
+    tx_buf[3] = (fm_u8)(((pkt_size-4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+// freq: 760 ~ 1080, 100KHz unit
+fm_s32 mt6620_tune_txscan(fm_u8 *tx_buf, fm_s32 tx_buf_size, fm_u16 freq)
+{
+    fm_s32 pkt_size = 0;
+
+    if(tx_buf_size < TX_BUF_SIZE){
+        return (-1);
+    }
+    
+    if (0 == fm_get_channel_space(freq)) {
+        freq *= 10;
+    }
+
+    freq = (freq - 6400) * 2 / 10;
+
+    tx_buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    tx_buf[1] = FM_TUNE_OPCODE;
+    pkt_size = 4;
+
+       //rampdown
+    //disable interrupt before rampdown
+    pkt_size += fm_bop_write(0x6B, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 6b 0000
+       pkt_size += fm_bop_modify(0x63, 0xFFF0, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 63[3:0] = 0, ramp down
+    pkt_size += fm_bop_rd_until(0x6f, 0x0001, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//Poll 6f[0] = b'0
+    pkt_size += fm_bop_modify(0x9C, 0xFFFF, 0x0008, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9c[3] = 1, ramp down
+    pkt_size += fm_bop_write(0x6B, 0x2100, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 6b 2100
+    //enable interrupt after rampdown
+
+       //set desired channel
+    pkt_size += fm_bop_modify(0x0F, 0xFC00, freq, &tx_buf[pkt_size], tx_buf_size - pkt_size);// set 0x0F[9:0] = 0x029e, => ((97.5 - 64) * 20)
+
+       //only for short antennal tune
+#ifdef MT6620_FM_USE_SHORT_ANTENNA
+       pkt_size += fm_bop_write(0x28, 0x3800, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 28 3800
+       pkt_size += fm_bop_write(0x03, 0x90F0, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 3 90f0
+       pkt_size += fm_bop_write(0x2E, 0x0028, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 2e 28
+       pkt_size += fm_bop_write(0x2F, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 2f 0
+       pkt_size += fm_bop_write(0x26, 0x003C, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 26 3c
+       pkt_size += fm_bop_write(0x2E, 0x002C, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 2e 2c
+       pkt_size += fm_bop_udelay(10000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wait 10ms
+       pkt_size += fm_bop_write(0x26, 0x0024, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 26 24
+       pkt_size += fm_bop_write(0x28, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 28 00
+#endif
+
+       //only for E1
+#ifdef MT6620E1
+    pkt_size += fm_bop_write(0x9F, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9F 0
+    pkt_size += fm_bop_write(0xAF, 0x2210, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr AF 2210
+#endif
+
+       //mask STC_DONE interrupt, 6a(D0) 0 
+       //pkt_size += fm_bop_modify(0x6A, 0xFFFE,  0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);
+
+       //enable hardware are controlled tuning sequence
+    pkt_size += fm_bop_modify(0x63, 0xFFFF,  0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);// set rgf_tune (63H D0) =1
+
+       //check STC_DONE interrupt status flag
+       //pkt_size += fm_bop_rd_until(0x69, 0x0001, 0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);//Poll fm_intr_stc_done (69H D0) = 1
+
+       //write 1 clear the STC_DONE status flag
+    //pkt_size += fm_bop_modify(0x69, 0xFFFF, 0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);// set stc_done (6FH D0) =1
+
+       //unmask STC_DONE interrupt, 6a(D0) 1
+       //pkt_size += fm_bop_modify(0x6A, 0xFFFF,  0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);
+
+       //only for E1
+#ifdef MT6620E1
+       //pkt_size += fm_bop_write(0xAF, 0x7710, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr AF 7710
+#endif
+
+    tx_buf[2] = (fm_u8)((pkt_size-4) & 0x00FF);
+    tx_buf[3] = (fm_u8)(((pkt_size-4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+/*
+ * mt6620_seek - execute seek action,
+ * @buf - target buf
+ * @buf_size - buffer size
+ * @seekdir - 0=seek up, 1=seek down
+ * @space - step, 50KHz:001, 100KHz:010, 200KHz:100
+ * @max_freq - upper bound
+ * @min_freq - lower bound
+ * return package size
+ */
+fm_s32 mt6620_seek_1(fm_u8 *buf, fm_s32 buf_size, fm_u16 seekdir, fm_u16 space, fm_u16 max_freq, fm_u16 min_freq)
+{
+    fm_s32 pkt_size = 0;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_SEEK_OPCODE;
+    pkt_size = 4;
+
+    //A1 Program seek direction, 0x66[10]: 0=seek up, 1=seek down
+    if (seekdir == 0) {
+        pkt_size += fm_bop_modify(0x66, 0xFBFF, 0x0000, &buf[pkt_size], buf_size - pkt_size);//0x66[10] = 0, seek up
+    } else {
+        pkt_size += fm_bop_modify(0x66, 0xFFFF, 0x0400, &buf[pkt_size], buf_size - pkt_size);//0x66[10] = 1, seek down
+    }
+
+    //0x66[11] 0=no wrarp, 1=wrap
+    pkt_size += fm_bop_modify(0x66, 0xFFFF, 0x0800, &buf[pkt_size], buf_size - pkt_size);//0x66[11] = 1, wrap
+    //A2 Program scan channel spacing, 0x66[14:12] step 50KHz:001/100KHz:010/200KHz:100
+    if (space == 4) {
+        pkt_size += fm_bop_modify(0x66, 0x8FFF, 0x4000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=001
+    } else {
+        pkt_size += fm_bop_modify(0x66, 0x8FFF, 0x2000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=010
+    }
+
+    //0x66[9:0] freq upper bound
+    max_freq = (max_freq - 640) * 2;
+    pkt_size += fm_bop_modify(0x66, 0xFC00, max_freq, &buf[pkt_size], buf_size - pkt_size);
+
+    //0x67[9:0] freq lower bound
+    min_freq = (min_freq - 640) * 2;
+    pkt_size += fm_bop_modify(0x67, 0xFC00, min_freq, &buf[pkt_size], buf_size - pkt_size);
+    //A3 Enable hardware controlled seeking sequence
+    pkt_size += fm_bop_modify(0x63, 0xFFFF, 0x0002, &buf[pkt_size], buf_size - pkt_size);//0x63[1] = 1
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+fm_s32 mt6620_seek_2(fm_u8 *buf, fm_s32 buf_size, fm_u16 seekdir, fm_u16 space, fm_u16 max_freq, fm_u16 min_freq)
+{
+    fm_s32 pkt_size = 0;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_SEEK_OPCODE;
+    pkt_size = 4;
+
+    //A10 Set softmute to normal mode
+    pkt_size += fm_bop_write(0x9F, 0x0001, &buf[pkt_size], buf_size - pkt_size);//wr 9F 1
+    pkt_size += fm_bop_write(0xC8, 0x0232, &buf[pkt_size], buf_size - pkt_size);//wr C8 232
+    pkt_size += fm_bop_write(0xDD, 0x8833, &buf[pkt_size], buf_size - pkt_size);//wr DD 8833
+    pkt_size += fm_bop_write(0xD8, 0x00E8, &buf[pkt_size], buf_size - pkt_size);//wr D8 E8
+    pkt_size += fm_bop_write(0x9F, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 9F 0
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+/*
+ * mt6620_scan - execute scan action,
+ * @buf - target buf
+ * @buf_size - buffer size
+ * @scandir - 0=seek up, 1=seek down
+ * @space - step, 50KHz:001, 100KHz:010, 200KHz:100
+ * @max_freq - upper bound
+ * @min_freq - lower bound
+ * return package size
+ */
+fm_s32 mt6620_scan_1(fm_u8 *buf, fm_s32 buf_size, fm_u16 scandir, fm_u16 space, fm_u16 max_freq, fm_u16 min_freq)
+{
+    fm_s32 pkt_size = 0;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_SCAN_OPCODE;
+    pkt_size = 4;
+
+    //A1 Program seek direction, 0x66[10]: 0=seek up, 1=seek down
+    if (scandir == 0) {
+        pkt_size += fm_bop_modify(0x66, 0xFBFF, 0x0000, &buf[pkt_size], buf_size - pkt_size);//0x66[10] = 0, seek up
+    } else {
+        pkt_size += fm_bop_modify(0x66, 0xFFFF, 0x0400, &buf[pkt_size], buf_size - pkt_size);//0x66[10] = 1, seek down
+    }
+
+    //0x66[11] 0=no wrarp, 1=wrap
+    pkt_size += fm_bop_modify(0x66, 0xFFFF, 0x0800, &buf[pkt_size], buf_size - pkt_size);//0x66[11] = 1, wrap
+    //A2 Program scan channel spacing, 0x66[14:12] step 50KHz:001/100KHz:010/200KHz:100
+    if (space == 4) {
+        pkt_size += fm_bop_modify(0x66, 0x8FFF, 0x4000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=001
+    } else {
+        pkt_size += fm_bop_modify(0x66, 0x8FFF, 0x2000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=010
+    }
+
+    //0x66[9:0] freq upper bound
+    max_freq = (max_freq - 640) * 2;
+    pkt_size += fm_bop_modify(0x66, 0xFC00, max_freq, &buf[pkt_size], buf_size - pkt_size);
+
+    //0x67[9:0] freq lower bound
+    min_freq = (min_freq - 640) * 2;
+    pkt_size += fm_bop_modify(0x67, 0xFC00, min_freq, &buf[pkt_size], buf_size - pkt_size);
+    //A3 Enable hardware controlled seeking sequence
+    pkt_size += fm_bop_modify(0x63, 0xFFFF, 0x0004, &buf[pkt_size], buf_size - pkt_size);//0x63[1] = 1
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+fm_s32 mt6620_scan_2(fm_u8 *buf, fm_s32 buf_size, fm_u16 scandir, fm_u16 space, fm_u16 max_freq, fm_u16 min_freq)
+{
+    fm_s32 pkt_size = 0;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_SCAN_OPCODE;
+    pkt_size = 4;
+
+    //A10 Set softmute to normal mode
+    pkt_size += fm_bop_write(0x9F, 0x0001, &buf[pkt_size], buf_size - pkt_size);//wr 9F 1
+    pkt_size += fm_bop_write(0xC8, 0x0232, &buf[pkt_size], buf_size - pkt_size);//wr C8 232
+    pkt_size += fm_bop_write(0xDD, 0x8833, &buf[pkt_size], buf_size - pkt_size);//wr DD 8833
+    pkt_size += fm_bop_write(0xD8, 0x00E8, &buf[pkt_size], buf_size - pkt_size);//wr D8 E8
+    pkt_size += fm_bop_write(0x9F, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 9F 0
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+fm_s32 mt6620_get_reg(fm_u8 *buf, fm_s32 buf_size, fm_u8 addr)
+{
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FSPI_READ_OPCODE;
+    buf[2] = 0x01;
+    buf[3] = 0x00;
+    buf[4] = addr;
+
+    WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4]);
+    return 5;
+}
+
+fm_s32 mt6620_set_reg(fm_u8 *buf, fm_s32 buf_size, fm_u8 addr, fm_u16 value)
+{
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FSPI_WRITE_OPCODE;
+    buf[2] = 0x03;
+    buf[3] = 0x00;
+    buf[4] = addr;
+    buf[5] = (fm_u8)((value) & 0x00FF);
+    buf[6] = (fm_u8)((value >> 8) & 0x00FF);
+
+    WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
+    return 7;
+}
+
+fm_s32 mt6620_rds_rx_enable(fm_u8 *tx_buf, fm_s32 tx_buf_size) //IC version
+{
+    fm_s32 pkt_size = 0;
+
+    if(tx_buf_size < TX_BUF_SIZE){
+        return (-1);
+    }
+    
+    tx_buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    tx_buf[1] = RDS_RX_ENABLE_OPCODE;
+    pkt_size = 4;
+
+    pkt_size += fm_bop_write(0x9F, 0x0003, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 0x9f 3
+    pkt_size += fm_bop_write(0xCB, 0xE016, &tx_buf[pkt_size], tx_buf_size - pkt_size);//Wr 0xcb e016
+    pkt_size += fm_bop_write(0x9F, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 0x9f 0
+    pkt_size += fm_bop_write(0x63, 0x0491, &tx_buf[pkt_size], tx_buf_size - pkt_size);//Wr 0x63 491
+    pkt_size += fm_bop_modify(0x6B, 0xFFFF, 0x2000, &tx_buf[pkt_size], TX_BUF_SIZE - pkt_size);//Wr 0x6b [13] = 1
+
+    tx_buf[2] = (fm_u8)((pkt_size-4) & 0x00FF);
+    tx_buf[3] = (fm_u8)(((pkt_size-4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+fm_s32 mt6620_rds_rx_disable(fm_u8 *tx_buf, fm_s32 tx_buf_size) //IC version
+{
+    fm_s32 pkt_size = 0;
+
+    if(tx_buf_size < TX_BUF_SIZE){
+        return (-1);
+    }
+    
+    tx_buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    tx_buf[1] = RDS_RX_ENABLE_OPCODE;
+    pkt_size = 4;
+
+    pkt_size += fm_bop_modify(0x6B, 0xDFFF, 0x0000, &tx_buf[pkt_size], TX_BUF_SIZE - pkt_size);//Wr 0x6b [13] = 0
+    pkt_size += fm_bop_write(0x63, 0x0481, &tx_buf[pkt_size], tx_buf_size - pkt_size);//Wr 0x63 481
+
+
+    tx_buf[2] = (fm_u8)((pkt_size-4) & 0x00FF);
+    tx_buf[3] = (fm_u8)(((pkt_size-4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+// TBD for IC
+fm_s32 mt6620_rds_tx(fm_u8 *tx_buf, fm_s32 tx_buf_size, fm_u16 pi, fm_u16 *ps, fm_u16 *other_rds, fm_u8 other_rds_cnt)
+{
+    fm_s32 pkt_size = 0;
+    fm_s32 i;
+
+    if(tx_buf_size < TX_BUF_SIZE){
+        return (-1);
+    }
+
+    if(other_rds_cnt > 29){
+        return (-2);
+    }
+
+    tx_buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    tx_buf[1] = RDS_TX_OPCODE;
+    pkt_size = 4;
+
+    //RDS Tx config
+    pkt_size += fm_bop_modify(0x65, 0xFFFF, 0x0010, &tx_buf[pkt_size], TX_BUF_SIZE - pkt_size);//wr 65[4] = b'1, enable RDS Tx
+    pkt_size += fm_bop_write(0x9F, 0x0003, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9F 3
+    pkt_size += fm_bop_write(0xA2, 0x0005, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a2 5, repeat + PI_reg mode
+    pkt_size += fm_bop_write(0xA1, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a1 0
+    //pkt_size += fm_bop_write(0xA0, 0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a0 1
+    pkt_size += fm_bop_write(0xA4, pi, &tx_buf[pkt_size], tx_buf_size - pkt_size);//write PI to PI_reg
+    //program PS buf
+    pkt_size += fm_bop_rd_until(0xAA, 0x0001, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);// rd until aa[0] = b'0, ptr in normal buf
+    //program normal buf, workaround that PS buf can't work while normal buf is empty
+    for(i = 0; i < 12; i++)
+    {
+        pkt_size += fm_bop_write(0xA8, ps[i], &tx_buf[pkt_size], tx_buf_size - pkt_size);//a8 = RDS Tx data
+    }
+    pkt_size += fm_bop_modify(0xA2, 0xFFFF, 0x0002, &tx_buf[pkt_size], TX_BUF_SIZE - pkt_size);//wr a2[1] = b'1, mem_addr mode
+    for(i = 0; i < 12; i++)
+    {
+        pkt_size += fm_bop_write(0xA7, (0x0063+i), &tx_buf[pkt_size], tx_buf_size - pkt_size);//a7 = mem_addr
+        pkt_size += fm_bop_write(0xA8, ps[i], &tx_buf[pkt_size], tx_buf_size - pkt_size);//a8 = RDS Tx data
+    }
+    pkt_size += fm_bop_modify(0xA2, 0xFFFF, 0x0010, &tx_buf[pkt_size], TX_BUF_SIZE - pkt_size);//wr a2[4] = b'1, switch to ps buf
+    //program normal buf
+    pkt_size += fm_bop_rd_until(0xAA, 0x0001, 0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);// rd until aa[0] = b'1, ptr in ps buf
+    pkt_size += fm_bop_modify(0xA2, 0xFFFD, 0x0000, &tx_buf[pkt_size], TX_BUF_SIZE - pkt_size);//wr a2[1] = b'0, h/w addr mode
+    for(i = 0; i < 12; i++)
+    {
+        pkt_size += fm_bop_write(0xA8, ps[i], &tx_buf[pkt_size], tx_buf_size - pkt_size);//a8 = RDS Tx data
+    }
+    for(i = 0; i < (other_rds_cnt * 3); i++)
+    {
+        pkt_size += fm_bop_write(0xA8, other_rds[i], &tx_buf[pkt_size], tx_buf_size - pkt_size);//a8 = RDS Tx data
+    }
+    pkt_size += fm_bop_modify(0xA2, 0xFFEF, 0x0000, &tx_buf[pkt_size], TX_BUF_SIZE - pkt_size);//wr a2[4] = b'0, switch to normal buf
+    pkt_size += fm_bop_write(0x9F, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9F 0
+
+    tx_buf[2] = (fm_u8)((pkt_size-4) & 0x00FF);
+    tx_buf[3] = (fm_u8)(((pkt_size-4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+// TBD for IC
+fm_s32 mt6620_off_2_tx_shortANA(fm_u8 *tx_buf, fm_s32 tx_buf_size)
+{
+    fm_s32 pkt_size = 0;
+
+    if(tx_buf_size < TX_BUF_SIZE){
+        return (-1);
+    }
+    
+    tx_buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    tx_buf[1] = FM_ENABLE_OPCODE;
+    pkt_size = 4;
+
+    pkt_size += fm_bop_write(0x01, 0x4A00, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 1 4A00  --> Turn on Central Bias + FC
+    pkt_size += fm_bop_udelay(30, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 30 
+    pkt_size += fm_bop_write(0x01, 0x6A00, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 1 6A00  --> Turn off FC
+    pkt_size += fm_bop_udelay(50, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 50
+    pkt_size += fm_bop_write(0x02, 0x299C, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 2 299C  --> Set the LDOs Output Voltages
+    pkt_size += fm_bop_write(0x01, 0x6B82, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 1 6B82  --> Turn on DCO, RX and ADDA LDO
+    pkt_size += fm_bop_write(0x3B, 0x0500, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 3B 0500 --> Turn on PA LDO --> LDO PA = 2.5V [0000 010x xxx0 000] {xxxx} - 0001 = 2.5V
+    pkt_size += fm_bop_write(0x04, 0x0548, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 4 0548  --> Set the RX LDO to Low Power Mode + TR Switch Off
+    pkt_size += fm_bop_write(0x37, 0x2000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 37 2000 --> Set the Short Antenna Bias
+    pkt_size += fm_bop_write(0x42, 0xC002, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 42 C002 --> Set the Short Antenna Bias
+    pkt_size += fm_bop_write(0x0A, 0x0060, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr A 0060  --> Update AFCDAC LPF Setting
+    pkt_size += fm_bop_write(0x0E, 0x0040, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr E 0040  --> Update SX_VDC_CBANK
+    pkt_size += fm_bop_write(0x0C, 0xA88C, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr c A88C
+    pkt_size += fm_bop_write(0x10, 0x1E8D, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 10 1e8d
+    pkt_size += fm_bop_write(0x27, 0x0005, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 27 0005 --> Update ACAL and Enable RMS_DET    
+    pkt_size += fm_bop_write(0x11, 0x07D8, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 11 07D8 --> Set VCO_DIVRST_N = 0 
+    pkt_size += fm_bop_write(0x41, 0x0003, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 41 0003 --> Set TX_FVCO_EN = 1 and FVCO_SEL=1
+    pkt_size += fm_bop_write(0x08, 0x25B8, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 8 25b8  --> ADC = TX Mode (AU_ADC)
+    pkt_size += fm_bop_write(0x09, 0x2964, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9 2964  --> ADC DWA ON
+    pkt_size += fm_bop_write(0x3F, 0xAD86, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 3F AD86 --> TX DAc RX_TX_SEL = TX MOde 
+    pkt_size += fm_bop_write(0x3A, 0x01EF, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 3A 01EF --> Turn on TX Chain [PA+D2S+HRM+AUPGA+TXDAC+LODIV]
+    pkt_size += fm_bop_write(0x3E, 0x3181, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 3E 3181 --> TX LPF EN + CSEL from RCCAL
+    pkt_size += fm_bop_write(0x00, 0x0100, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 0  0100 --> Turn on SDADC
+    pkt_size += fm_bop_write(0x37, 0x2000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 37 2000 --> Control Signal for DAC_CK output clock gate
+    //FM ADPLL Power Up
+    pkt_size += fm_bop_write(0x25, 0x040F, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 25 040f --> Turn off DIG_CK_EN
+    pkt_size += fm_bop_write(0x20, 0x2720, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 20 2720 --> Turn on ADPLL  2320 CW32 
+    //XHC,2011/03/18, [wr 22 9980-> 6680]
+    pkt_size += fm_bop_write(0x22, 0x6680, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 22 9980 --> Update DLF Gain
+    pkt_size += fm_bop_write(0x25, 0x080F, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 25 080f --> Update I_CODE_CCAL + ADC_CK_EN + 32KCLKPLL_EN 0803 CW37
+    pkt_size += fm_bop_write(0x1E, 0x0863, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 1e 0863 --> Turn on DCO + CAL_COARSE_EN
+    pkt_size += fm_bop_udelay(5000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 5000
+    pkt_size += fm_bop_write(0x1E, 0x0865, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 1e 0865 --> Change the CAL_COARSE to CAL_FINE
+    pkt_size += fm_bop_udelay(5000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 5000
+    pkt_size += fm_bop_write(0x1E, 0x0871, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 1e 0871 --> Off the CAL_COARSE and CAL_FINE + Turn on PLL
+    pkt_size += fm_bop_udelay(100000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 100000
+    pkt_size += fm_bop_write(0x2A, 0x1026, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 2a 1022 --> Enable TOP_CG
+    //FM RC Calibration
+    pkt_size += fm_bop_write(0x00, 0x0080, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 0 0080 --> RCCAL
+    pkt_size += fm_bop_udelay(1, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 1000
+    pkt_size += fm_bop_write(0x1B, 0x0094, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 1b 0094 --> Update RCCAL Target Count
+    pkt_size += fm_bop_write(0x1B, 0x0095, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 1b 0095 --> Start RCCAL
+    pkt_size += fm_bop_udelay(200, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 1000
+    pkt_size += fm_bop_write(0x1B, 0x0094, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 1b 0094 --> Off RCCAL
+    pkt_size += fm_bop_write(0x00, 0x0100, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 0 0100 --> Turn off RCCAL Analog Block
+    //FM VCO Enable
+    pkt_size += fm_bop_write(0x01, 0x6B8A, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 1 6B8A --> Turn on VCO LDO
+    pkt_size += fm_bop_udelay(1, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 1000
+    pkt_size += fm_bop_write(0x00, 0xC100, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 0 C100 --> Turn on VCO, AFCDAC
+    pkt_size += fm_bop_write(0x0C, 0xB88C, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr c B88c --> Turn on Const gm
+    pkt_size += fm_bop_udelay(3000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 3000
+    pkt_size += fm_bop_write(0x3A, 0x01FF, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 3A 01FF --> Enable TX Divider
+    //Short Antenna Setting
+    pkt_size += fm_bop_write(0x42, 0xF002, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 42 F002 --> MSB of HRM_Gain <5> ****>> For Max Pout 
+    pkt_size += fm_bop_write(0x3C, 0xABE9, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 3C ABE9 --> Max HRM Gain<4:0> - xxxxx [1010 10xx xxx0 1001]
+    pkt_size += fm_bop_write(0x3D, 0x027E, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 3D 027E --> Max PA Gain<4:0> - [0000 0010 0xxx xx10]
+    pkt_size += fm_bop_write(0x33, 0x0008, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 33 0008 --> Use old VCO calibration routine to save calibration time
+    pkt_size += fm_bop_write(0x28, 0xFFFF, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 28 FFFF
+    pkt_size += fm_bop_write(0x2E, 0x0020, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 2E 0020 --> Turn on SCAL_HWTRIG_DIS --> VCO CAL and SCAL are done separately
+    pkt_size += fm_bop_write(0x2F, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 2F 0000 --> Disable Capbank manual enter mode [4A40 previously]
+    pkt_size += fm_bop_write(0x44, 0x006E, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 44 6e
+    pkt_size += fm_bop_write(0x46, 0xDC22, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 46 DC22
+    pkt_size += fm_bop_write(0x49, 0x0080, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 49 80
+    pkt_size += fm_bop_write(0x4A, 0x0004, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 4A 4
+    pkt_size += fm_bop_write(0x4B, 0x0040, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 4B 40
+
+    tx_buf[2] = (fm_u8)((pkt_size-4) & 0x00FF);
+    tx_buf[3] = (fm_u8)(((pkt_size-4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+// TBD for IC
+fm_s32 mt6620_dig_init(fm_u8 *tx_buf, fm_s32 tx_buf_size)
+{
+    fm_s32 pkt_size = 0;
+
+    if(tx_buf_size < TX_BUF_SIZE){
+        return (-1);
+    }
+    
+    tx_buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    tx_buf[1] = FM_ENABLE_OPCODE;
+    pkt_size = 4;
+
+//fm_rgf_maincon
+    pkt_size += fm_bop_write(0x64, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 64 0
+    pkt_size += fm_bop_write(0x65, 0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 65 1
+    pkt_size += fm_bop_write(0x68, 0xE100, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 68 E100
+    pkt_size += fm_bop_udelay(10000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//delay 10000   
+    pkt_size += fm_bop_write(0x68, 0xE000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 68 E000
+//fm_rgf_dac
+    pkt_size += fm_bop_write(0x9F, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9F 0
+    pkt_size += fm_bop_write(0x9E, 0x001C, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9E 1C
+    pkt_size += fm_bop_write(0x9C, 0xA540, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9c A540
+//fm_rgf_front
+    pkt_size += fm_bop_write(0x9F, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9f 0 --> start rgf_front
+    pkt_size += fm_bop_write(0xB8, 0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr b8 1
+    pkt_size += fm_bop_write(0xAB, 0x39B6, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr ab 39b6
+    pkt_size += fm_bop_write(0xAC, 0x3C3E, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr ac 3c3e
+    pkt_size += fm_bop_write(0xAD, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr ad 0 
+    pkt_size += fm_bop_write(0xAE, 0x03C2, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr ae 3c2
+    pkt_size += fm_bop_write(0xAF, 0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr af 1
+    pkt_size += fm_bop_write(0xB1, 0x623D, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr b1 623d 
+    pkt_size += fm_bop_write(0xF4, 0x0020, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr f4 20
+    pkt_size += fm_bop_write(0xF5, 0xBF16, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr f5 bf16
+    pkt_size += fm_bop_write(0xB9, 0x0050, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr b9 0050
+    pkt_size += fm_bop_write(0xBA, 0x00C3, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr ba 00c3
+    pkt_size += fm_bop_write(0xBB, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr bb 0
+    pkt_size += fm_bop_write(0xBC, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr bc 0
+    pkt_size += fm_bop_write(0xBD, 0x0056, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr bd 56 
+    pkt_size += fm_bop_write(0xBE, 0x0089, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr be 89
+    pkt_size += fm_bop_write(0xBF, 0x004C, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr bf 4c
+    pkt_size += fm_bop_write(0xC0, 0x0171, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr c0 171
+    pkt_size += fm_bop_write(0xC1, 0x002B, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr c1 2b
+    pkt_size += fm_bop_write(0xC2, 0x001F, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr c2 1f
+    pkt_size += fm_bop_write(0xC3, 0x0066, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr c3 66
+    pkt_size += fm_bop_write(0xC4, 0x00F6, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr c4 f6
+    pkt_size += fm_bop_write(0xC5, 0x0066, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr c5 66
+    pkt_size += fm_bop_write(0xC6, 0x001F, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr c6 1f
+    pkt_size += fm_bop_write(0xC7, 0x0007, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr c7 7 
+    pkt_size += fm_bop_write(0xFE, 0x0039, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr fe 39
+    pkt_size += fm_bop_write(0xFF, 0x3907, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr ff 3907
+//fm_rgf_fmx
+    pkt_size += fm_bop_write(0x9F, 0x0001, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9f 1 --> start rgf_outer
+    pkt_size += fm_bop_write(0xC0, 0x076C, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr c0 76c
+    pkt_size += fm_bop_write(0xB7, 0x0004, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr b7 4
+    pkt_size += fm_bop_write(0xD8, 0x006A, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr d8 6a
+    pkt_size += fm_bop_write(0xC8, 0x2828, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr c8 2828
+    pkt_size += fm_bop_write(0xCE, 0x0090, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr ce 90
+    pkt_size += fm_bop_write(0xFE, 0x000F, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr fe f
+    pkt_size += fm_bop_write(0xA2, 0x0100, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a2 100
+    pkt_size += fm_bop_write(0xA3, 0x0111, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a3 111
+    pkt_size += fm_bop_write(0xA4, 0x0122, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a4 122
+    pkt_size += fm_bop_write(0xA5, 0x0135, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a5 135
+    pkt_size += fm_bop_write(0xA6, 0x0149, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a6 149
+    pkt_size += fm_bop_write(0xA7, 0x015E, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a7 15e
+    pkt_size += fm_bop_write(0xDB, 0x0174, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr db 174
+    pkt_size += fm_bop_write(0xDC, 0x018D, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr dc 18d
+    pkt_size += fm_bop_write(0xC9, 0x01A6, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr c9 1a6
+    pkt_size += fm_bop_write(0xCA, 0x01C1, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr ca 1c1
+    pkt_size += fm_bop_write(0xCB, 0x01DE, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr cb 1de
+    pkt_size += fm_bop_write(0xCC, 0x01FD, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr cc 1fd
+    pkt_size += fm_bop_write(0xD4, 0x2657, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr d4 2657
+    pkt_size += fm_bop_write(0xA0, 0x85B2, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr a0 85b2
+    pkt_size += fm_bop_write(0x9F, 0x0000, &tx_buf[pkt_size], tx_buf_size - pkt_size);//wr 9f 0
+
+    tx_buf[2] = (fm_u8)((pkt_size-4) & 0x00FF);
+    tx_buf[3] = (fm_u8)(((pkt_size-4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6620/pub/mt6620_fm_config.c b/drivers/mtk_wcn_combo/drv_fm/mt6620/pub/mt6620_fm_config.c
new file mode 100755 (executable)
index 0000000..1b16332
--- /dev/null
@@ -0,0 +1,357 @@
+/* fm_config.c
+ *
+ * (C) Copyright 2011
+ * MediaTek <www.MediaTek.com>
+ * hongcheng <hongcheng.xia@MediaTek.com>
+ *
+ * FM Radio Driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "fm_typedef.h"
+#include "fm_rds.h"
+#include "fm_dbg.h"
+#include "fm_err.h"
+#include "fm_stdlib.h"
+#include "fm_patch.h"
+#include "fm_config.h"
+//#include "fm_cust_cfg.h"
+#include "mt6620_fm_cust_cfg.h"
+
+fm_cust_cfg mt6620_fm_config;
+//static fm_s32 fm_index = 0;
+
+static fm_s32 MT6620fm_cust_config_print(fm_cust_cfg *cfg)
+{
+ //   fm_s32 i;
+
+    WCN_DBG(FM_NTC | MAIN, "MT6620 rssi_l:\t%d\n", cfg->rx_cfg.long_ana_rssi_th);
+    WCN_DBG(FM_NTC | MAIN, "MT6620 rssi_s:\t%d\n", cfg->rx_cfg.short_ana_rssi_th);
+    WCN_DBG(FM_NTC | MAIN, "MT6620 pamd_th:\t%d\n", cfg->rx_cfg.pamd_th);
+    WCN_DBG(FM_NTC | MAIN, "MT6620 mr_th:\t%d\n", cfg->rx_cfg.mr_th);
+    WCN_DBG(FM_NTC | MAIN, "MT6620 atdc_th:\t%d\n", cfg->rx_cfg.atdc_th);
+    WCN_DBG(FM_NTC | MAIN, "MT6620 prx_th:\t%d\n", cfg->rx_cfg.prx_th);
+    WCN_DBG(FM_NTC | MAIN, "MT6620 atdev_th:\t%d\n", cfg->rx_cfg.atdev_th);
+    WCN_DBG(FM_NTC | MAIN, "MT6620 smg_th:\t%d\n", cfg->rx_cfg.smg_th);
+    WCN_DBG(FM_NTC | MAIN, "MT6620 de_emphasis:\t%d\n", cfg->rx_cfg.deemphasis);
+    WCN_DBG(FM_NTC | MAIN, "MT6620 osc_freq:\t%d\n", cfg->rx_cfg.osc_freq);
+    
+    WCN_DBG(FM_NTC | MAIN, "MT6620 scan_hole_low:\t%d\n", cfg->tx_cfg.scan_hole_low);
+    WCN_DBG(FM_NTC | MAIN, "MT6620 scan_hole_high:\t%d\n", cfg->tx_cfg.scan_hole_high);
+    WCN_DBG(FM_NTC | MAIN, "MT6620 power_level:\t%d\n", cfg->tx_cfg.power_level);
+#if 0
+    WCN_DBG(FM_NTC | MAIN, "MT6620 rssi_l:\t0x%04x\n", cfg->rx_cfg.long_ana_rssi_th);
+    WCN_DBG(FM_NTC | MAIN, "MT6620 rssi_s:\t0x%04x\n", cfg->rx_cfg.short_ana_rssi_th);
+    WCN_DBG(FM_NTC | MAIN, "MT6620 mr_th:\t0x%04x\n", cfg->rx_cfg.mr_th);
+    WCN_DBG(FM_NTC | MAIN, "MT6620 cqi_th:\t0x%04x\n", cfg->rx_cfg.cqi_th);
+    WCN_DBG(FM_NTC | MAIN, "MT6620 smg_th:\t0x%04x\n", cfg->rx_cfg.smg_th);
+    WCN_DBG(FM_NTC | MAIN, "MT6620 scan_ch_size:\t%d\n", cfg->rx_cfg.scan_ch_size);
+    WCN_DBG(FM_NTC | MAIN, "MT6620 seek_space:\t%d\n", cfg->rx_cfg.seek_space);
+    WCN_DBG(FM_NTC | MAIN, "MT6620 band:\t%d\n", cfg->rx_cfg.band);
+    WCN_DBG(FM_NTC | MAIN, "MT6620 band_freq_l:\t%d\n", cfg->rx_cfg.band_freq_l);
+    WCN_DBG(FM_NTC | MAIN, "MT6620 band_freq_h:\t%d\n", cfg->rx_cfg.band_freq_h);
+    WCN_DBG(FM_NTC | MAIN, "MT6620 scan_sort:\t%d\n", cfg->rx_cfg.scan_sort);
+    WCN_DBG(FM_NTC | MAIN, "MT6620 fake_ch_num:\t%d\n", cfg->rx_cfg.fake_ch_num);
+    WCN_DBG(FM_NTC | MAIN, "MT6620 fake_ch_rssi_th:\t%d\n", cfg->rx_cfg.fake_ch_rssi_th);
+
+    for (i = 0; i < cfg->rx_cfg.fake_ch_num; i++) {
+        WCN_DBG(FM_NTC | MAIN, "fake_ch:\t%d\n", cfg->rx_cfg.fake_ch[i]);
+    }
+
+    WCN_DBG(FM_NTC | MAIN, "de_emphasis:\t%d\n", cfg->rx_cfg.deemphasis);
+    WCN_DBG(FM_NTC | MAIN, "osc_freq:\t%d\n", cfg->rx_cfg.osc_freq);
+    WCN_DBG(FM_NTC | MAIN, "scan_hole_low:\t%d\n", cfg->tx_cfg.scan_hole_low);
+    WCN_DBG(FM_NTC | MAIN, "scan_hole_high:\t%d\n", cfg->tx_cfg.scan_hole_high);
+    WCN_DBG(FM_NTC | MAIN, "power_level:\t%d\n", cfg->tx_cfg.power_level);
+#endif
+    return 0;
+}
+
+static fm_s32 MT6620cfg_item_handler(fm_s8 *grp, fm_s8 *key, fm_s8 *val, fm_cust_cfg *cfg)
+{
+    fm_s32 ret = 0;
+    struct fm_rx_cust_cfg *rx_cfg = &cfg->rx_cfg;
+    struct fm_tx_cust_cfg *tx_cfg = &cfg->tx_cfg;
+
+    if (0 <= (ret = cfg_item_match(key, val, "FM_RX_RSSI_TH_LONG_MT6620", &rx_cfg->long_ana_rssi_th))) 
+    {//FMR_RSSI_TH_L = 0x0301
+        return ret;
+    } 
+    else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_RSSI_TH_SHORT_MT6620", &rx_cfg->short_ana_rssi_th))) 
+    {
+        return ret;
+    } 
+    else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_DESENSE_RSSI_MT6620", &rx_cfg->desene_rssi_th))) 
+    {
+        return ret;
+    } 
+    else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_PAMD_TH_MT6620", &rx_cfg->pamd_th))) 
+    {
+        return ret;
+    } 
+    else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_MR_TH_MT6620", &rx_cfg->mr_th))) 
+    {
+        return ret;
+    } 
+    else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_ATDC_TH_MT6620", &rx_cfg->atdc_th))) 
+    {
+        return ret;
+    } 
+    else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_PRX_TH_MT6620", &rx_cfg->prx_th))) 
+    {
+        return ret;
+    } 
+    else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_SMG_TH_MT6620", &rx_cfg->smg_th))) 
+    {
+        return ret;
+    } 
+    else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_DEEMPHASIS_MT6620", &rx_cfg->deemphasis))) 
+    {
+        return ret;
+    } 
+    else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_OSC_FREQ_MT6620", &rx_cfg->osc_freq))) 
+    {
+        return ret;
+    } 
+    else if (0 <= (ret = cfg_item_match(key, val, "FMT_SCAN_HOLE_L_MT6620", &tx_cfg->scan_hole_low))) 
+    {
+        return ret;
+    } 
+    else if (0 <= (ret = cfg_item_match(key, val, "FMT_SCAN_HOLE_H_MT6620", &tx_cfg->scan_hole_high))) 
+    {
+        return ret;
+    } 
+    else if (0 <= (ret = cfg_item_match(key, val, "FMT_PWR_LVL_MAX_MT6620", &tx_cfg->power_level))) 
+    {
+        return ret;
+    } 
+    else 
+    {
+        WCN_DBG(FM_WAR | MAIN, "invalid key\n");
+        return -1;
+    }
+/*    if (0 <= (ret = cfg_item_match(key, val, "FMR_RSSI_TH_L_MT6620", &rx_cfg->long_ana_rssi_th))) {//FMR_RSSI_TH_L = 0x0301
+        return ret;
+    } else if (0 <= (ret = cfg_item_match(key, val, "FMR_RSSI_TH_S_MT6620", &rx_cfg->short_ana_rssi_th))) {
+        return ret;
+    } else if (0 <= (ret = cfg_item_match(key, val, "FMR_CQI_TH_MT6620", &rx_cfg->cqi_th))) {
+        return ret;
+    } else if (0 <= (ret = cfg_item_match(key, val, "FMR_MR_TH_MT6620", &rx_cfg->mr_th))) {
+        return ret;
+    } else if (0 <= (ret = cfg_item_match(key, val, "FMR_SMG_TH_MT6620", &rx_cfg->smg_th))) {
+        return ret;
+    } else if (0 <= (ret = cfg_item_match(key, val, "FMR_SCAN_CH_SIZE_MT6620", &rx_cfg->scan_ch_size))) {
+        return ret;
+    } else if (0 <= (ret = cfg_item_match(key, val, "FMR_SCAN_SORT_MT6620", &rx_cfg->scan_sort))) {
+        return ret;
+    } else if (0 <= (ret = cfg_item_match(key, val, "FMR_SEEK_SPACE_MT6620", &rx_cfg->seek_space))) {
+        return ret;
+    } else if (0 <= (ret = cfg_item_match(key, val, "FMR_BAND_MT6620", &rx_cfg->band))) {
+        return ret;
+    } else if (0 <= (ret = cfg_item_match(key, val, "FMR_BAND_FREQ_L_MT6620", &rx_cfg->band_freq_l))) {
+        return ret;
+    } else if (0 <= (ret = cfg_item_match(key, val, "FMR_BAND_FREQ_H_MT6620", &rx_cfg->band_freq_h))) {
+        return ret;
+    } else if (0 <= (ret = cfg_item_match(key, val, "FMR_FAKE_CH_MT6620", &rx_cfg->fake_ch[fm_index]))) {
+        fm_index += 1;
+        rx_cfg->fake_ch_num = (rx_cfg->fake_ch_num < fm_index) ? fm_index : rx_cfg->fake_ch_num;
+        return ret;
+    } else if (0 <= (ret = cfg_item_match(key, val, "FMR_FAKE_CH_RSSI_MT6620", &rx_cfg->fake_ch_rssi_th))) {
+        return ret;
+    } else if (0 <= (ret = cfg_item_match(key, val, "FMR_DEEMPHASIS_MT6620", &rx_cfg->deemphasis))) {
+        return ret;
+    } else if (0 <= (ret = cfg_item_match(key, val, "FMR_OSC_FREQ_MT6620", &rx_cfg->osc_freq))) {
+        return ret;
+    } */
+}
+static fm_s32 MT6620fm_cust_config_default(fm_cust_cfg *cfg)
+{
+    FMR_ASSERT(cfg);
+
+    cfg->rx_cfg.long_ana_rssi_th = FM_RX_RSSI_TH_LONG_MT6620;
+    cfg->rx_cfg.short_ana_rssi_th = FM_RX_RSSI_TH_SHORT_MT6620;
+    cfg->rx_cfg.desene_rssi_th = FM_RX_DESENSE_RSSI_MT6620;
+    cfg->rx_cfg.pamd_th = FM_RX_PAMD_TH_MT6620;
+    cfg->rx_cfg.mr_th = FM_RX_MR_TH_MT6620;
+    cfg->rx_cfg.atdc_th = FM_RX_ATDC_TH_MT6620;
+    cfg->rx_cfg.prx_th = FM_RX_PRX_TH_MT6620;
+    cfg->rx_cfg.smg_th = FM_RX_SMG_TH_MT6620;
+    cfg->rx_cfg.deemphasis = FM_RX_DEEMPHASIS_MT6620;
+       cfg->rx_cfg.osc_freq = FM_RX_OSC_FREQ_MT6620;
+
+    cfg->tx_cfg.scan_hole_low = FM_TX_SCAN_HOLE_LOW_MT6620;
+    cfg->tx_cfg.scan_hole_high = FM_TX_SCAN_HOLE_HIGH_MT6620;
+    cfg->tx_cfg.power_level = FM_TX_PWR_LEVEL_MAX_MT6620;
+
+    return 0;
+}
+
+static fm_s32 MT6620fm_cust_config_file(const fm_s8 *filename, fm_cust_cfg *cfg)
+{
+    fm_s32 ret = 0;
+    fm_s8 *buf = NULL;
+    fm_s32 file_len = 0;
+
+    if (!(buf = fm_zalloc(4096))) {
+        WCN_DBG(FM_ALT | MAIN, "-ENOMEM\n");
+        return -ENOMEM;
+    }
+
+//    fm_index = 0;
+
+    file_len = fm_file_read(filename, buf, 4096, 0);
+
+    if (file_len <= 0) {
+        ret = -1;
+        goto out;
+    }
+
+    ret = cfg_parser(buf, MT6620cfg_item_handler, cfg);
+
+out:
+
+    if (buf) {
+        fm_free(buf);
+    }
+
+    return ret;
+}
+#define MT6620_FM_CUST_CFG_PATH "etc/fmr/mt6620_fm_cust.cfg"
+fm_s32 MT6620fm_cust_config_setup(const fm_s8 *filepath)
+{
+    fm_s32 ret = 0;
+    fm_s8 *filep = NULL;
+    fm_s8 file_path[51] = {0};
+
+    MT6620fm_cust_config_default(&mt6620_fm_config);
+    WCN_DBG(FM_NTC | MAIN, "MT6620 FM default config\n");
+    MT6620fm_cust_config_print(&mt6620_fm_config);
+
+    if (!filepath) {
+        filep = MT6620_FM_CUST_CFG_PATH;
+    } else {
+        memcpy(file_path, filepath, (strlen(filepath) > 50) ? 50 : strlen(filepath));
+        filep = file_path;
+        trim_path(&filep);
+    }
+
+    ret = MT6620fm_cust_config_file(filep, &mt6620_fm_config);
+    WCN_DBG(FM_NTC | MAIN, "MT6620 FM cust config\n");
+    MT6620fm_cust_config_print(&mt6620_fm_config);
+       
+    return ret;
+}
+
+fm_u16 MT6620fm_cust_config_fetch(enum fm_cust_cfg_op op_code)
+{
+#if 0
+    fm_u16 tmp = 0;
+    fm_s32 i;
+    static fm_s32 fake_ch_idx = 0;
+
+    switch (op_code) {
+        //For FM RX
+    case FM_CFG_RX_RSSI_TH_LONG: {
+        tmp = mt6620_fm_config.rx_cfg.long_ana_rssi_th;
+        break;
+    }
+    case FM_CFG_RX_RSSI_TH_SHORT: {
+        tmp = mt6620_fm_config.rx_cfg.short_ana_rssi_th;
+        break;
+    }
+    case FM_CFG_RX_CQI_TH: {
+        tmp = mt6620_fm_config.rx_cfg.cqi_th;
+        break;
+    }
+    case FM_CFG_RX_MR_TH: {
+        tmp = mt6620_fm_config.rx_cfg.mr_th;
+        break;
+    }
+    case FM_CFG_RX_SMG_TH: {
+        tmp = mt6620_fm_config.rx_cfg.smg_th;
+        break;
+    }
+    case FM_CFG_RX_SCAN_CH_SIZE: {
+        tmp = mt6620_fm_config.rx_cfg.scan_ch_size;
+        break;
+    }
+    case FM_CFG_RX_SEEK_SPACE: {
+        tmp = mt6620_fm_config.rx_cfg.seek_space;
+        break;
+    }
+    case FM_CFG_RX_BAND: {
+        tmp = mt6620_fm_config.rx_cfg.band;
+        break;
+    }
+    case FM_CFG_RX_BAND_FREQ_L: {
+        tmp = mt6620_fm_config.rx_cfg.band_freq_l;
+        break;
+    }
+    case FM_CFG_RX_BAND_FREQ_H: {
+        tmp = mt6620_fm_config.rx_cfg.band_freq_h;
+        break;
+    }
+    case FM_CFG_RX_SCAN_SORT: {
+        tmp = mt6620_fm_config.rx_cfg.scan_sort;
+        break;
+    }
+    case FM_CFG_RX_FAKE_CH_NUM: {
+        tmp = mt6620_fm_config.rx_cfg.fake_ch_num;
+        break;
+    }
+    case FM_CFG_RX_FAKE_CH: {
+        tmp = mt6620_fm_config.rx_cfg.fake_ch[fake_ch_idx];
+        i = (mt6620_fm_config.rx_cfg.fake_ch_num > 0) ? mt6620_fm_config.rx_cfg.fake_ch_num : FAKE_CH_MAX;
+        fake_ch_idx++;
+        fake_ch_idx = fake_ch_idx % i;
+        break;
+    }
+    case FM_CFG_RX_FAKE_CH_RSSI: {
+        tmp = mt6620_fm_config.rx_cfg.fake_ch_rssi_th;
+        break;
+    }
+    case FM_CFG_RX_DEEMPHASIS: {
+        tmp = mt6620_fm_config.rx_cfg.deemphasis;
+        break;
+    }
+    case FM_CFG_RX_OSC_FREQ: {
+        tmp = mt6620_fm_config.rx_cfg.osc_freq;
+        break;
+    }
+    //For FM TX
+    case FM_CFG_TX_SCAN_HOLE_LOW: {
+        tmp = mt6620_fm_config.tx_cfg.scan_hole_low;
+        break;
+    }
+    case FM_CFG_TX_SCAN_HOLE_HIGH: {
+        tmp = mt6620_fm_config.tx_cfg.scan_hole_high;
+        break;
+    }
+    case FM_CFG_TX_PWR_LEVEL: {
+        tmp = mt6620_fm_config.tx_cfg.power_level;
+        break;
+    }
+    default:
+        break;
+    }
+
+    WCN_DBG(FM_DBG | MAIN, "mt6620_cust cfg %d: 0x%04x\n", op_code, tmp);
+    return tmp;
+#endif
+       return 0;
+}
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6620/pub/mt6620_fm_eint.c b/drivers/mtk_wcn_combo/drv_fm/mt6620/pub/mt6620_fm_eint.c
new file mode 100755 (executable)
index 0000000..4ab2d35
--- /dev/null
@@ -0,0 +1,55 @@
+/* mt6620_fm_eint.c
+ *
+ * (C) Copyright 2009 
+ * MediaTek <www.MediaTek.com>
+ * Hongcheng <hongcheng.xia@MediaTek.com>
+ *
+ * MT6620 FM Radio Driver -- EINT functions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+ #if 0
+#include "stp_exp.h"
+#include "wmt_exp.h"
+
+#include "fm_typedef.h"
+#include "fm_dbg.h"
+#include "fm_err.h"
+#include "fm_eint.h"
+       
+fm_s32 fm_enable_eint(void)
+{
+       return 0;
+}
+
+fm_s32 fm_disable_eint(void)
+{
+       return 0;
+}
+
+fm_s32 fm_request_eint(void (*parser)(void))
+{
+    WCN_DBG(FM_NTC|EINT,"%s\n", __func__);
+
+    mtk_wcn_stp_register_event_cb(FM_TASK_INDX, parser);
+    
+       return 0;
+}
+
+fm_s32 fm_eint_pin_cfg(fm_s32 mode)
+{      
+       return 0;
+}
+#endif
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6620/pub/mt6620_fm_lib.c b/drivers/mtk_wcn_combo/drv_fm/mt6620/pub/mt6620_fm_lib.c
new file mode 100755 (executable)
index 0000000..cb8ff82
--- /dev/null
@@ -0,0 +1,2212 @@
+#include <linux/semaphore.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+
+#include "stp_exp.h"
+#include "wmt_exp.h"
+
+#include "fm_typedef.h"
+#include "fm_dbg.h"
+#include "fm_err.h"
+#include "fm_interface.h"
+#include "fm_stdlib.h"
+#include "fm_utils.h"
+#include "fm_patch.h"
+#include "fm_link.h"
+#include "fm_config.h"
+#include "fm_private.h"
+
+#include "mt6620_fm_reg.h"
+#include "mt6620_fm.h"
+//#include "mt6620_drv_dsp.h"
+//#include "mt6620_fm_link.h"
+#include "mt6620_fm_lib.h"
+#include "mt6620_fm_cmd.h"
+#include "mt6620_fm_cust_cfg.h"
+#ifdef MTK_FM_50KHZ_SUPPORT
+static struct fm_fifo *cqi_fifo = NULL;
+#endif
+extern fm_cust_cfg mt6620_fm_config;
+static struct fm_hw_info mt6620_hw_info = {
+    .chip_id = 0x00006620,
+    .eco_ver = 0x00000000,
+    .rom_ver = 0x00000002,
+    .patch_ver = 0x00000111,
+    .reserve = 0x00000000,
+};
+static struct fm_i2s_info mt6620_i2s_inf = {
+    .status = 0,    //i2s off
+    .mode = 0,      //slave mode
+    .rate = 48000,  //48000 sample rate
+};
+
+fm_s32 MT6620_HL_Side_Adj(fm_u16 freq, fm_s32 *hl);
+fm_s32 MT6620_ADPLL_Freq_Avoid(fm_u16 freq, fm_s32 *freqavoid);
+fm_s32 MT6620_MCU_Freq_Avoid(fm_u16 freq, fm_s32 *freqavoid);
+fm_s32 MT6620_ADPLL_Power_OnOff(fm_s32 onoff, fm_s32 ADPLL_clk);
+fm_s32 MT6620_TX_PWR_CTRL(fm_u16 freq, fm_s32 *ctr);
+fm_s32 MT6620_RTC_Drift_CTRL(fm_u16 freq, fm_s32 *ctr);
+fm_s32 MT6620_TX_DESENSE(fm_u16 freq, fm_s32 *ctr);
+
+static fm_s32 mt6620_I2s_Setting(fm_s32 onoff, fm_s32 mode, fm_s32 sample);
+static fm_s32 mt6620_desense_check(fm_u16 freq,fm_s32 rssi);
+static fm_s32 MT6620_Rds_Tx(fm_u16 pi, fm_u16 *ps, fm_u16 *other_rds, fm_u8 other_rds_cnt);
+static fm_s32 MT6620_Rds_Tx_Enable(void);
+static fm_s32 MT6620_Rds_Tx_Disable(void);
+
+static fm_u8 *cmd_buf = NULL;
+static struct fm_lock *cmd_buf_lock = NULL;
+static struct fm_callback *fm_cb_op;
+//static struct MT6620fm_priv priv_adv_6620;
+static ENUM_WMTHWVER_TYPE_T hw_ver=WMTHWVER_MT6620_E3;
+static fm_s32 mt6620_pwron(fm_s32 data)
+{
+    if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_FM)) {
+        WCN_DBG(FM_ALT | CHIP, "WMT turn on FM Fail!\n");
+        return -FM_ELINK;
+    } else {
+                /* GeorgeKuo: turn on function before check stp ready */
+               if(fm_false == mtk_wcn_stp_is_ready())
+               {
+                       WCN_DBG(FM_ALT | MAIN,"6620 stp is not ready, please retry later\n");
+                       return -FM_ELINK;
+               }
+               hw_ver = mtk_wcn_wmt_hwver_get();
+        WCN_DBG(FM_ALT | CHIP, "WMT turn on FM OK!\n");
+        return 0;
+    }
+}
+
+
+static fm_s32 mt6620_pwroff(fm_s32 data)
+{
+    if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_off(WMTDRV_TYPE_FM)) {
+        WCN_DBG(FM_ALT | CHIP, "WMT turn off FM Fail!\n");
+        return -FM_ELINK;
+    } else {
+        WCN_DBG(FM_NTC | CHIP, "WMT turn off FM OK!\n");
+        return 0;
+    }
+}
+
+static fm_s32 Delayms(fm_u32 data)
+{
+    WCN_DBG(FM_DBG | CHIP, "delay %dms\n", data);
+    msleep(data);
+    return 0;
+}
+
+static fm_s32 Delayus(fm_u32 data)
+{
+    WCN_DBG(FM_DBG | CHIP, "delay %dus\n", data);
+    udelay(data);
+    return 0;
+}
+
+static struct fm_res_ctx *res = NULL;
+
+fm_s32 mt6620_get_read_result(struct fm_res_ctx* result)
+{
+    FMR_ASSERT(result);
+    res = result;
+
+    return 0;
+}
+
+static fm_s32 mt6620_read(fm_u8 addr, fm_u16 *val)
+{
+    fm_s32 ret = 0;
+    fm_u16 pkt_size;
+
+    if (FM_LOCK(cmd_buf_lock)) 
+               return (-FM_ELOCK);
+    pkt_size = mt6620_get_reg(cmd_buf, TX_BUF_SIZE, addr);
+    ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_FSPI_RD, SW_RETRY_CNT, FSPI_RD_TIMEOUT, mt6620_get_read_result);
+
+    if (!ret && res) {
+        *val = res->fspi_rd;
+    }
+
+    FM_UNLOCK(cmd_buf_lock);
+
+    return ret;
+}
+
+static fm_s32 mt6620_write(fm_u8 addr, fm_u16 val)
+{
+    fm_s32 ret = 0;
+    fm_u16 pkt_size;
+
+    if (FM_LOCK(cmd_buf_lock)) 
+               return (-FM_ELOCK);
+    pkt_size = mt6620_set_reg(cmd_buf, TX_BUF_SIZE, addr, val);
+    ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_FSPI_WR, SW_RETRY_CNT, FSPI_WR_TIMEOUT, NULL);
+    FM_UNLOCK(cmd_buf_lock);
+
+    return ret;
+}
+
+static fm_s32 mt6620_set_bits(fm_u8 addr, fm_u16 bits, fm_u16 mask)
+{
+    fm_s32 ret = 0;
+    fm_u16 val;
+
+    ret = mt6620_read(addr, &val);
+
+    if (ret)
+        return ret;
+
+    val = ((val & (mask)) | bits);
+    ret = mt6620_write(addr, val);
+
+    return ret;
+}
+
+static fm_u16 mt6620_get_chipid(void)
+{
+    return 0x6620;
+}
+
+/*  mt6620_SetAntennaType - set Antenna type
+ *  @type - 1,Short Antenna;  0, Long Antenna
+ */
+static fm_s32 mt6620_SetAntennaType(fm_s32 type)
+{
+    WCN_DBG(FM_DBG | CHIP, "set ana to %s\n", type ? "short" : "long");
+
+    if (type == FM_ANA_LONG) {
+        //Long Antenna RSSI threshold, 0xE0 D0~D9
+        mt6620_write(0xE0, ((0xA301 & 0xFC00) | (FMR_RSSI_TH_LONG_MT6620 & 0x03FF)));
+        //Turn on Short Antenna LNA and Off TR Switch
+        mt6620_write(0x04, 0x0142);
+        //Turn off the Short Antenna Capbank biasing
+        mt6620_write(0x05, 0x00E7);
+        //Turn off the Short Antenna Capbank biasing
+        mt6620_write(0x26, 0x0004);
+        //Disable concurrent calibration for VCO and SCAL
+        mt6620_write(0x2E, 0x0008);
+    } else if (type == FM_ANA_SHORT) {
+        //Short Antenna RSSI threshold, 0xE0 D0~D9
+        mt6620_write(0xE0, ((0xA2E0 & 0xFC00) | (FMR_RSSI_TH_SHORT_MT6620 & 0x03FF)));
+        //Turn on Short Antenna LNA and TR Switch
+        mt6620_write(0x04, 0x0145);
+        //Turn on the Short Antenna Capbank biasing
+        mt6620_write(0x05, 0x00FF);
+        //Turn on the Short Antenna Capbank biasing
+        mt6620_write(0x26, 0x0024);
+        //Enable concurrent calibration for VCO and SCAL
+        mt6620_write(0x2E, 0x0000);
+    } else {
+        WCN_DBG(FM_ERR | CHIP, "%s()\n", __func__);
+        return -FM_EPARA;
+    }
+
+    return 0;
+}
+
+static fm_s32 mt6620_GetAntennaType(void)
+{
+    fm_u16 dataRead;
+
+    mt6620_read(0x2E, &dataRead);
+
+    if (dataRead == 0x0000)
+        return FM_ANA_SHORT; //short antenna
+    else
+        return FM_ANA_LONG; //long antenna
+}
+
+static fm_s32 mt6620_Mute(fm_bool mute)
+{
+    WCN_DBG(FM_DBG | CHIP, "set %s\n", mute ? "mute" : "unmute");
+
+    if (mute) {
+        return mt6620_set_bits(0x9C, 0x0008, 0xFFF7); //1:9C D3 = 1
+    } else {
+        return mt6620_set_bits(0x9c, 0x0000, 0xFFF7); //1:9C D3 = 0
+    }
+}
+
+static fm_s32 mt6620_RampDown(void)
+{
+    fm_s32 ret = 0;
+    fm_u16 pkt_size;
+
+    WCN_DBG(FM_NTC | CHIP, "ramp down\n");
+
+    if (FM_LOCK(cmd_buf_lock)) 
+               return (-FM_ELOCK);
+    pkt_size = mt6620_rampdown(cmd_buf, TX_BUF_SIZE);
+    ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_RAMPDOWN, SW_RETRY_CNT, RAMPDOWN_TIMEOUT, NULL);
+    FM_UNLOCK(cmd_buf_lock);
+
+    if (ret) {
+        WCN_DBG(FM_ERR | CHIP, "ramp down failed\n");
+    }
+
+    return ret;
+}
+#if 0//ramp down tx will do in tx tune  flow
+static fm_s32 MT6620_RampDown_Tx(void)
+{
+    fm_s32 ret = 0;
+    fm_u16 pkt_size = 0;
+
+    WCN_DBG(FM_NTC | CHIP, "ramp down TX\n");
+    if (FM_LOCK(cmd_buf_lock)) 
+               return (-FM_ELOCK);
+    
+    pkt_size = mt6620_rampdown_tx(cmd_buf, TX_BUF_SIZE);
+    ret = fm_cmd_tx(cmd_buf, pkt_size,FLAG_RAMPDOWN, SW_RETRY_CNT, RAMPDOWN_TIMEOUT,NULL);
+    
+    FM_UNLOCK(cmd_buf_lock);
+    if (ret) {
+        WCN_DBG(FM_ERR | CHIP, "ramp down TX failed\n");
+    }
+    return ret;
+}
+#endif
+static fm_s32 mt6620_PowerUp(fm_u16 *chip_id, fm_u16 *device_id)
+{
+    fm_s32 ret = 0;
+    fm_u16 pkt_size;
+
+    FMR_ASSERT(chip_id);
+    FMR_ASSERT(device_id);
+
+    WCN_DBG(FM_DBG | CHIP, "pwr on seq......\n");
+
+    //Wholechip FM Power Up: step 1, mt6620_off_2_longANA
+    if (FM_LOCK(cmd_buf_lock)) 
+               return (-FM_ELOCK);
+    pkt_size = mt6620_off_2_longANA_1(cmd_buf, TX_BUF_SIZE);
+    ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_EN, SW_RETRY_CNT, EN_TIMEOUT, NULL);
+    FM_UNLOCK(cmd_buf_lock);
+
+    if (ret) {
+        WCN_DBG(FM_ALT | CHIP, "mt6620_off_2_longANA_1 failed\n");
+        return ret;
+    }
+
+    Delayms(100);
+
+    if (FM_LOCK(cmd_buf_lock)) 
+               return (-FM_ELOCK);
+    pkt_size = mt6620_off_2_longANA_2(cmd_buf, TX_BUF_SIZE);
+    ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_EN, SW_RETRY_CNT, EN_TIMEOUT, NULL);
+    FM_UNLOCK(cmd_buf_lock);
+
+    if (ret) {
+        WCN_DBG(FM_ALT | CHIP, "mt6620_off_2_longANA_2 failed\n");
+        return ret;
+    }
+
+    Delayms(50);
+
+   // *chip_id = 0x6620;
+   // *device_id = 0x6620;
+   // WCN_DBG(FM_NTC | CHIP, "chip_id:0x%04x\n", 0x6620);
+
+    //Wholechip FM Power Up: step 2, FM Digital Init: fm_rgf_maincon
+    if (FM_LOCK(cmd_buf_lock)) 
+               return (-FM_ELOCK);
+    pkt_size = mt6620_pwrup_digital_init_1(cmd_buf, TX_BUF_SIZE);
+    ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_EN, SW_RETRY_CNT, EN_TIMEOUT, NULL);
+    FM_UNLOCK(cmd_buf_lock);
+
+    if (ret) {
+        WCN_DBG(FM_ALT | CHIP, "mt6620_pwrup_digital_init_2 failed\n");
+        return ret;;
+    }
+
+    Delayms(10);
+
+    if (FM_LOCK(cmd_buf_lock)) 
+               return (-FM_ELOCK);
+    pkt_size = mt6620_pwrup_digital_init_2(cmd_buf, TX_BUF_SIZE);
+    ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_EN, SW_RETRY_CNT, EN_TIMEOUT, NULL);
+    FM_UNLOCK(cmd_buf_lock);
+
+    if (ret) {
+        WCN_DBG(FM_ALT | CHIP, "mt6620_pwrup_digital_init_2 failed\n");
+        return ret;;
+    }
+
+    Delayms(10);
+
+    if (FM_LOCK(cmd_buf_lock)) 
+               return (-FM_ELOCK);
+    pkt_size = mt6620_pwrup_digital_init_3(cmd_buf, TX_BUF_SIZE);
+    ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_EN, SW_RETRY_CNT, EN_TIMEOUT, NULL);
+    FM_UNLOCK(cmd_buf_lock);
+
+    if (ret) {
+        WCN_DBG(FM_ALT | CHIP, "mt6620_pwrup_digital_init_3 failed\n");
+        return ret;;
+    }
+#ifdef FM_DIGITAL_INPUT
+  #ifdef MT6573 //for MT6573
+               if(get_chip_eco_ver() == CHIP_E1){
+                       ret = mt6620_I2s_Setting(MT6620_I2S_ON, MT6620_I2S_MASTER, MT6620_I2S_48K);
+               }else{
+                       ret = mt6620_I2s_Setting(MT6620_I2S_ON, MT6620_I2S_SLAVE, MT6620_I2S_48K);
+               }
+  #else
+               ret = mt6620_I2s_Setting(MT6620_I2S_ON, MT6620_I2S_SLAVE, MT6620_I2S_48K);
+  #endif
+               if(ret){
+                       WCN_DBG(FM_ERR |CHIP,"pwron set I2S on error\n");
+                       return ret;
+               }
+               //we will disable 6620 fm chip analog output when use I2S path, set 0x3A bit2 = 0
+               //mt6620_set_bits(0x3A, 0, MASK(2));
+               WCN_DBG(FM_NTC |CHIP,"pwron set I2S on ok\n");
+#endif
+
+    mt6620_hw_info.eco_ver = (fm_s32)mtk_wcn_wmt_hwver_get();
+    WCN_DBG(FM_DBG | CHIP, "pwr on seq ok\n");
+    return ret;
+}
+static fm_s32 mt6620_PowerUpTx(void)
+{
+    fm_s32 ret = 0;
+    fm_u16 pkt_size;
+    fm_u16 dataRead;
+
+    WCN_DBG(FM_DBG | CHIP, "pwr on Tx seq......\n");
+
+    if (FM_LOCK(cmd_buf_lock)) 
+               return (-FM_ELOCK);
+    pkt_size = mt6620_off_2_tx_shortANA(cmd_buf, TX_BUF_SIZE);
+    ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_EN, SW_RETRY_CNT, EN_TIMEOUT, NULL);
+    FM_UNLOCK(cmd_buf_lock);
+
+    if (ret) {
+        WCN_DBG(FM_ALT | CHIP, "mt6620_off_2_tx_shortANA failed\n");
+        return ret;
+    }
+
+
+    mt6620_read(0x62, &dataRead);
+       WCN_DBG(FM_NTC | CHIP, "Tx on chipid=%x\n",dataRead);
+    
+    if (FM_LOCK(cmd_buf_lock)) 
+               return (-FM_ELOCK);
+    pkt_size = mt6620_dig_init(cmd_buf, TX_BUF_SIZE);
+    ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_EN, SW_RETRY_CNT, EN_TIMEOUT, NULL);
+    FM_UNLOCK(cmd_buf_lock);
+
+    if (ret) {
+        WCN_DBG(FM_ALT | CHIP, "mt6620_dig_init failed\n");
+        return ret;
+    }
+    //get temprature
+    if(mtk_wcn_wmt_therm_ctrl(WMTTHERM_ENABLE) != fm_true)
+    {
+               WCN_DBG(FM_ERR | MAIN, "wmt_therm_ctrl, WMTTHERM_ENABLE failed\n");
+       ret = -FM_ELINK;
+       return ret;
+    }
+#ifdef FM_DIGITAL_INPUT
+               ret = mt6620_I2s_Setting(MT6620_I2S_ON, MT6620_I2S_SLAVE, MT6620_I2S_48K);
+               if(ret){
+                       WCN_DBG(FM_ERR |CHIP,"pwron tx set I2S on error\n");
+                       return ret;
+               }
+               //we will disable 6620 fm chip analog output when use I2S path, set 0x3A bit2 = 0
+               //mt6620_set_bits(0x3A, 0, MASK(2));
+               WCN_DBG(FM_NTC |CHIP,"pwron set I2S on ok\n");
+#endif
+
+    WCN_DBG(FM_DBG | CHIP, "pwr on tx seq ok\n");
+    return ret;
+}
+
+static fm_s32 mt6620_PowerDown(void)
+{
+    fm_s32 ret = 0;
+    fm_u16 pkt_size;
+
+    WCN_DBG(FM_DBG | CHIP, "pwr down seq\n");
+
+   // mt6620_RampDown();
+
+    if (FM_LOCK(cmd_buf_lock)) 
+               return (-FM_ELOCK);
+    pkt_size = mt6620_pwrdown(cmd_buf, TX_BUF_SIZE);
+    ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_EN, SW_RETRY_CNT, EN_TIMEOUT, NULL);
+    FM_UNLOCK(cmd_buf_lock);
+
+    if (ret) {
+        WCN_DBG(FM_ALT | CHIP, "mt6620_pwrdown failed\n");
+        return ret;
+    }
+
+    return ret;
+}
+
+static fm_s32 mt6620_PowerDownTx(void)
+{
+    fm_s32 ret = 0;
+
+   if(mtk_wcn_wmt_therm_ctrl(WMTTHERM_DISABLE) != fm_true)
+   {
+          WCN_DBG(FM_ERR | MAIN, "wmt_therm_ctrl, WMTTHERM_DISABLE failed\n");
+          ret = -FM_ELINK;
+   }
+
+    return ret;
+}
+
+static fm_bool MT6620_SetFreq_Tx(fm_u16 freq)
+{
+    fm_s32 ret = 0;
+    fm_u16 pkt_size;
+
+    fm_cb_op->cur_freq_set(freq);
+    //start tune
+    if (FM_LOCK(cmd_buf_lock)) 
+               return (-FM_ELOCK);
+    pkt_size = mt6620_tune_tx(cmd_buf, TX_BUF_SIZE, freq);
+    ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_TUNE, SW_RETRY_CNT, TUNE_TIMEOUT, NULL);
+    FM_UNLOCK(cmd_buf_lock);
+
+    if (ret) {
+        WCN_DBG(FM_ALT | CHIP, "mt6620_tune_tx failed\n");
+        return ret;;
+    }
+
+       Delayms(125);
+
+    WCN_DBG(FM_DBG | CHIP, "mt6620_tune_tx to %d ok\n", freq);
+
+    return fm_true;
+}
+
+/*
+ * fm_print_curCQI -- print cur freq's CQI
+ * @cur_freq, current frequency
+ * If OK, return 0, else error code
+ */
+static fm_s32 mt6620_print_curCQI(fm_u16 cur_freq)
+{
+    fm_s32 ret = 0;
+    fm_u16 rssi = 0;
+    fm_u16 pamd = 0;
+    fm_u16 mr = 0;
+
+    if((ret = mt6620_write(FM_MAIN_PGSEL, FM_PG0)))
+        return ret;
+    if((ret = mt6620_read(FM_RSSI_IND, &rssi)))
+        return ret;
+    if((ret = mt6620_read(FM_ADDR_PAMD, &pamd)))
+        return ret;
+    if((ret = mt6620_read(FM_MR_IND, &mr)))
+        return ret;
+    
+    WCN_DBG(FM_NTC |CHIP,"FREQ=%d, RSSI=0x%04x, PAMD=0x%04x, MR=0x%04x\n", (fm_s32)cur_freq, rssi, pamd, mr);
+    return ret;    
+}
+
+static fm_bool mt6620_SetFreq(fm_u16 freq)
+{
+    fm_s32 ret = 0;
+    fm_s32 hl_side = -1;
+    fm_s32 freq_avoid = -1;
+    fm_u16 pkt_size;
+
+    fm_cb_op->cur_freq_set(freq);
+
+       if((ret = MT6620_HL_Side_Adj(freq, &hl_side)))
+               return ret;
+       WCN_DBG(FM_NTC |CHIP,"%s, [hl_side=%d]\n", __func__, hl_side);
+       
+       if((ret = MT6620_ADPLL_Freq_Avoid(freq, &freq_avoid)))
+               return ret;
+       WCN_DBG(FM_NTC |CHIP,"%s, adpll [freq_avoid=%d]\n", __func__, freq_avoid);
+       
+//     hw_ver = mtk_wcn_wmt_hwver_get();
+       if(hw_ver >= WMTHWVER_MT6620_E3)
+       {
+               if((ret = MT6620_MCU_Freq_Avoid(freq, &freq_avoid)))
+                       return ret;
+               WCN_DBG(FM_NTC |CHIP,"%s, mcu [freq_avoid=%d]\n", __func__, freq_avoid);
+       }
+       else
+       {
+               WCN_DBG(FM_NTC |CHIP,"%s, no need do mcu freq avoid[hw_ver=%d]\n", __func__, hw_ver);
+       }
+       
+    //start tune
+    if (FM_LOCK(cmd_buf_lock)) 
+               return (-FM_ELOCK);
+    pkt_size = mt6620_tune_1(cmd_buf, TX_BUF_SIZE, freq);
+    ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_TUNE, SW_RETRY_CNT, TUNE_TIMEOUT, NULL);
+    FM_UNLOCK(cmd_buf_lock);
+
+    if (ret) {
+        WCN_DBG(FM_ALT | CHIP, "mt6620_tune_1 failed\n");
+        return ret;;
+    }
+
+    Delayms(200);
+
+    if (FM_LOCK(cmd_buf_lock)) 
+               return (-FM_ELOCK);
+    pkt_size = mt6620_tune_2(cmd_buf, TX_BUF_SIZE, freq);
+    ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_TUNE, SW_RETRY_CNT, TUNE_TIMEOUT, NULL);
+    FM_UNLOCK(cmd_buf_lock);
+
+    if (ret) {
+        WCN_DBG(FM_ALT | CHIP, "mt6620_tune_2 failed\n");
+        return ret;;
+    }
+
+    Delayms(35);
+
+    if (FM_LOCK(cmd_buf_lock)) 
+               return (-FM_ELOCK);
+    pkt_size = mt6620_tune_3(cmd_buf, TX_BUF_SIZE, freq);
+    ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_TUNE, SW_RETRY_CNT, TUNE_TIMEOUT, NULL);
+    FM_UNLOCK(cmd_buf_lock);
+
+    if (ret) {
+        WCN_DBG(FM_ALT | CHIP, "mt6620_tune_3 failed\n");
+        return ret;;
+    }
+
+    ret = mt6620_print_curCQI(freq);
+    WCN_DBG(FM_DBG | CHIP, "set freq to %d ok\n", freq);
+
+    return fm_true;
+}
+
+
+static fm_s32 mt6620_TxScan_SetFreq(fm_u16 freq)
+{
+    fm_s32 ret = 0;
+    fm_u16 pkt_size = 0;
+
+    WCN_DBG(FM_NTC | CHIP,"+%s():[freq=%d]\n", __func__, freq);
+    if (FM_LOCK(cmd_buf_lock)) 
+               return (-FM_ELOCK);
+    
+    pkt_size = mt6620_tune_txscan(cmd_buf, TX_BUF_SIZE, freq);
+    ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_TUNE, SW_RETRY_CNT, TUNE_TIMEOUT, NULL);
+    FM_UNLOCK(cmd_buf_lock);
+    
+    FM_UNLOCK(cmd_buf_lock);
+    WCN_DBG(FM_NTC | CHIP,"-%s():[ret=%d]\n", __func__, ret);
+    return ret;
+}
+
+static fm_s32 mt6620_TxScan_GetCQI(fm_s16 *pRSSI, fm_s16 *pPAMD, fm_s16 *pMR)
+{
+    fm_s32 cnt = 0;
+    fm_s32 ret = 0;
+       fm_s16 tmp_reg = 0;
+       fm_s16 aRSSI = 0;
+       fm_s16 aPAMD = 0;
+       fm_s16 aMR = 0;
+       
+    WCN_DBG(FM_NTC | CHIP,"+%s():\n", __func__);
+
+       if((pRSSI == NULL) || (pPAMD == NULL) || (pMR == NULL)){
+        WCN_DBG(FM_ERR | CHIP,"%s():para error, [pRSSI=%p],[aPAMD=%p],[pMR=%p]\n", 
+            __func__, pRSSI, pPAMD, pMR);
+        ret = -FM_EPARA;
+               goto out;
+       }
+       
+       for(cnt = 0; cnt < 8; cnt++)
+       {
+               Delayms(3);
+               if((ret = mt6620_read(FM_RSSI_IND, &tmp_reg)))
+            goto out;
+               tmp_reg = tmp_reg&0x03ff;
+               tmp_reg = (tmp_reg > 511) ? ((fm_s16)(tmp_reg-1024)) : tmp_reg;
+               aRSSI += tmp_reg;
+               
+               if((ret = mt6620_read(FM_ADDR_PAMD, &tmp_reg)))
+            goto out;
+               tmp_reg = tmp_reg&0x00ff;
+               tmp_reg = (tmp_reg > 127) ? ((fm_s16)(tmp_reg-256)) : tmp_reg;
+               aPAMD += tmp_reg;
+               
+               if((ret = mt6620_read(FM_MR_IND, &tmp_reg)))
+            goto out;
+               tmp_reg = tmp_reg&0x01ff;
+               tmp_reg = (tmp_reg > 255) ? ((fm_s16)(tmp_reg-512)) : tmp_reg;
+               aMR += tmp_reg;
+       }
+
+       *pRSSI = aRSSI>>3;
+       *pPAMD = aPAMD>>3;
+       *pMR = aMR>>3;
+
+    WCN_DBG(FM_NTC | CHIP,"%s():[RSSI=%d],[PAMD=%d],[MR=%d]\n", 
+            __func__, *pRSSI, *pPAMD, *pMR);
+    
+out:
+    WCN_DBG(FM_NTC | CHIP,"-%s():[ret=%d]\n", __func__, ret);
+    return ret;
+}
+
+static fm_s32 mt6620_TxScan_IsEmptyChannel(fm_s16 RSSI, fm_s16 PAMD, fm_s16 MR, fm_s32 *empty)
+{
+    fm_s32 ret = 0;
+    
+    WCN_DBG(FM_NTC | CHIP,"+%s():[RSSI=%d],[PAMD=%d],[MR=%d]\n", __func__, RSSI, PAMD, MR);
+
+    if(empty == NULL)
+    {
+        WCN_DBG(FM_NTC | CHIP,"invalid pointer [empty=0x%x]!\n", (fm_u32)empty);
+        ret = -FM_EPARA;
+        goto out;
+    }
+
+    *empty = fm_true; 
+       if(RSSI > FM_TXSCAN_RSSI_TH){
+           *empty = fm_false;
+        goto out;
+       }
+
+       if(PAMD < FM_TXSCAN_PAMD_TH){
+               *empty = fm_false;
+        goto out;
+       }
+
+       if(MR < FM_TXSCAN_MR_TH){
+               *empty = fm_false;
+        goto out;
+       }
+
+out:
+    WCN_DBG(FM_NTC | CHIP,"-%s():[ret=%d]\n", __func__, ret);
+    return ret;
+}
+
+static fm_s32 mt6620_TxScan(fm_u16 min_freq, 
+                                                               fm_u16 max_freq,
+                                       fm_u16 *pFreq,
+                                       fm_u16 *pScanTBL,
+                                       fm_u16 *ScanTBLsize,
+                                       fm_u16 scandir,
+                                       fm_u16 space)
+{
+       fm_s32 ret = 0;
+       fm_u16 freq = *pFreq;
+       fm_u16 scan_cnt = *ScanTBLsize;
+       fm_u16 cnt = 0; 
+       fm_s16 rssi = 0;
+       fm_s16 pamd = 0;
+       fm_s16 mr = 0;
+       fm_s32 counter = 0;
+    fm_s32 empty = -1;
+    fm_s32 step;
+
+    WCN_DBG(FM_NTC | CHIP,"+%s():\n", __func__);
+    
+    if((!pScanTBL) || (*ScanTBLsize < FM_TX_SCAN_MIN) || (*ScanTBLsize >  FM_TX_SCAN_MAX))
+    {
+        WCN_DBG(FM_ERR | CHIP,"+%s():invalid scan table\n", __func__);
+        ret = -FM_EPARA;
+        goto out;
+    }
+
+    WCN_DBG(FM_NTC | CHIP, "[freq=%d], [max_freq=%d],[min_freq=%d],[scan BTL size=%d],[scandir=%d],[space=%d]\n", 
+                       *pFreq, max_freq, min_freq, *ScanTBLsize, scandir, space);
+
+       cnt = 0;
+   /* if (space == MT6620_FM_SPACE_100K) {
+        step = 1;
+    } else if (space == MT6620_FM_SPACE_50K) {
+        step = 5;
+    } else if (space == MT6620_FM_SPACE_200K) {
+        step = 2;
+    } else {
+        //default
+        step = 1;
+    }*/
+    step = space;
+       while(!(!(cnt < scan_cnt) || (freq > max_freq) || (freq < min_freq))){
+               //MT6620_RampDown();
+               //Set desired channel, tune to the channel, and perform fast AGC
+               counter++; //just for debug
+               
+               ret = mt6620_TxScan_SetFreq(freq);
+               if(ret){
+            WCN_DBG(FM_ERR | CHIP,"%s():set freq failed\n", __func__);
+                       goto out;
+               }
+               
+               //wait 8~10ms for RF setting
+               Delayms(10);
+               //wait 4 AAGC period for AAGC setting, AAGC period = 1024/480k = 2.13ms
+               Delayms(9);
+               
+               ret = mt6620_TxScan_GetCQI(&rssi, &pamd, &mr);
+               if(ret){
+            WCN_DBG(FM_ERR | CHIP,"%s():get CQI failed\n", __func__);
+                       goto out;
+               }
+
+               ret = mt6620_TxScan_IsEmptyChannel(rssi, pamd, mr, &empty);
+               if(!ret){
+            if((empty == fm_true) && ((freq < FM_TX_SCAN_HOLE_LOW) || (freq > FM_TX_SCAN_HOLE_HIGH))){
+                *(pScanTBL + cnt) = freq; //strore the valid empty channel 
+                           cnt++;
+                WCN_DBG(FM_NTC | CHIP,"empty channel:[freq=%d] [cnt=%d]\n", freq, cnt);
+            }                  
+               }else{ 
+                   WCN_DBG(FM_ERR | CHIP,"%s():IsEmptyChannel failed\n", __func__);
+                       goto out;
+        }
+
+               if(scandir == FM_TX_SCAN_UP){
+            if(freq == FM_TX_SCAN_HOLE_LOW){
+                freq += (FM_TX_SCAN_HOLE_HIGH - FM_TX_SCAN_HOLE_LOW + step);
+            }else{
+                freq += step;
+            }
+               }else if(scandir == FM_TX_SCAN_DOWN){
+                   if(freq == FM_TX_SCAN_HOLE_HIGH){
+                freq -= (FM_TX_SCAN_HOLE_HIGH - FM_TX_SCAN_HOLE_LOW + step);
+            }else{
+                freq -= step;
+            }
+               }else{
+            WCN_DBG(FM_ERR | CHIP,"%s():scandir para error\n", __func__);
+                       ret = -FM_EPARA;
+            goto out;
+               }
+       }
+
+       *ScanTBLsize = cnt;
+       *pFreq = *(pScanTBL + cnt);
+       WCN_DBG(FM_NTC | CHIP, "completed, [cnt=%d],[freq=%d],[counter=%d]\n", cnt, freq, counter);
+    
+out:
+    WCN_DBG(FM_NTC | CHIP,"-%s():[ret=%d]\n", __func__, ret);
+    return ret;
+}
+
+/*
+* mt6620_Seek
+* @pFreq - IN/OUT parm, IN start freq/OUT seek valid freq
+* @seekdir - 0:up, 1:down
+* @space - 1:50KHz, 2:100KHz, 4:200KHz
+* return fm_true:seek success; fm_false:seek failed
+*/
+static fm_bool mt6620_Seek(fm_u16 min_freq, fm_u16 max_freq, fm_u16 *pFreq, fm_u16 seekdir, fm_u16 space)
+{
+    fm_s32 ret = 0;
+    fm_u16 pkt_size,temp;
+
+    mt6620_RampDown();
+    mt6620_read(0x9C, &temp);
+    mt6620_Mute(fm_true);
+
+    if (FM_LOCK(cmd_buf_lock)) 
+               return (-FM_ELOCK);
+    pkt_size = mt6620_seek_1(cmd_buf, TX_BUF_SIZE, seekdir, space, max_freq, min_freq);
+    ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_SEEK | FLAG_SEEK_DONE, SW_RETRY_CNT, SEEK_TIMEOUT, mt6620_get_read_result);
+    FM_UNLOCK(cmd_buf_lock);
+
+    if (!ret && res) {
+        *pFreq = res->seek_result;
+        fm_cb_op->cur_freq_set(*pFreq);
+    } else {
+        WCN_DBG(FM_ALT | CHIP, "mt6620_seek_1 failed\n");
+        return ret;
+    }
+
+    Delayms(35);
+
+    if (FM_LOCK(cmd_buf_lock)) 
+               return (-FM_ELOCK);
+    pkt_size = mt6620_seek_2(cmd_buf, TX_BUF_SIZE, seekdir, space, max_freq, min_freq);
+    ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_SEEK | FLAG_SEEK_DONE, SW_RETRY_CNT, SEEK_TIMEOUT, mt6620_get_read_result);
+    FM_UNLOCK(cmd_buf_lock);
+
+    if (ret) {
+        WCN_DBG(FM_ALT | CHIP, "mt6620_seek_2 failed\n");
+        return ret;
+    }
+
+    //get the result freq
+    WCN_DBG(FM_NTC | CHIP, "seek, result freq:%d\n", *pFreq);
+       if((temp&0x0008) == 0)
+       {
+    mt6620_Mute(fm_false);
+       }
+
+    return fm_true;
+}
+
+static fm_bool mt6620_Scan(fm_u16 min_freq, fm_u16 max_freq, fm_u16 *pFreq, fm_u16 *pScanTBL,
+                           fm_u16 *ScanTBLsize, fm_u16 scandir, fm_u16 space)
+{
+    fm_s32 ret = 0;
+    fm_u16 pkt_size,temp;
+    fm_u16 offset = 0;
+    fm_u16 tmp_scanTBLsize = *ScanTBLsize;
+
+    if ((!pScanTBL) || (tmp_scanTBLsize == 0)) {
+        WCN_DBG(FM_ALT | CHIP, "scan, failed:invalid scan table\n");
+        return fm_false;
+    }
+
+    WCN_DBG(FM_DBG | CHIP, "start freq: %d, max_freq:%d, min_freq:%d, scan BTL size:%d, scandir:%d, space:%d\n", *pFreq, max_freq, min_freq, *ScanTBLsize, scandir, space);
+
+    mt6620_RampDown();
+    mt6620_read(0x9C, &temp);
+    mt6620_Mute(fm_true);
+
+    if (FM_LOCK(cmd_buf_lock)) 
+               return (-FM_ELOCK);
+    pkt_size = mt6620_scan_1(cmd_buf, TX_BUF_SIZE, scandir, space, max_freq, min_freq);
+    ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_SCAN | FLAG_SCAN_DONE, SW_RETRY_CNT, SCAN_TIMEOUT, mt6620_get_read_result);
+    FM_UNLOCK(cmd_buf_lock);
+
+    if (!ret && res) {
+        fm_memcpy(pScanTBL, res->scan_result, sizeof(fm_u16)*FM_SCANTBL_SIZE);
+        WCN_DBG(FM_INF | CHIP, "Rx Scan Result:\n");
+
+        for (offset = 0; offset < tmp_scanTBLsize; offset++) {
+            WCN_DBG(FM_INF | CHIP, "%d: %04x\n", (fm_s32)offset, *(pScanTBL + offset));
+        }
+
+        *ScanTBLsize = tmp_scanTBLsize;
+    } else {
+        WCN_DBG(FM_ALT | CHIP, "mt6620_scan_1 failed\n");
+        return ret;
+    }
+
+    Delayms(35);
+
+    if (FM_LOCK(cmd_buf_lock)) 
+               return (-FM_ELOCK);
+    pkt_size = mt6620_scan_2(cmd_buf, TX_BUF_SIZE, scandir, space, max_freq, min_freq);
+    ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_SEEK | FLAG_SEEK_DONE, SW_RETRY_CNT, SEEK_TIMEOUT, mt6620_get_read_result);
+    FM_UNLOCK(cmd_buf_lock);
+
+    if (ret) {
+        WCN_DBG(FM_ALT | CHIP, "mt6620_scan_2 failed\n");
+        return ret;
+    }
+
+       if((temp&0x0008) == 0)
+       {
+    mt6620_Mute(fm_false);
+       }
+
+    return fm_true;
+}
+
+/*
+ * mt6620_GetCurRSSI - get current freq's RSSI value
+ * RS=RSSI
+ * If RS>511, then RSSI(dBm)= (RS-1024)/16*6
+ *                                else RSSI(dBm)= RS/16*6
+ */
+static fm_s32 mt6620_GetCurRSSI(fm_s32 *pRSSI)
+{
+    fm_u16 tmp_reg;
+
+    mt6620_read(FM_RSSI_IND, &tmp_reg);
+    tmp_reg = tmp_reg & 0x03ff;
+
+    if (pRSSI) {
+        *pRSSI = (tmp_reg > 511) ? (((tmp_reg - 1024) * 6) >> 4) : ((tmp_reg * 6) >> 4);
+        WCN_DBG(FM_DBG | CHIP, "rssi:%d, dBm:%d\n", tmp_reg, *pRSSI);
+    } else {
+        WCN_DBG(FM_ERR | CHIP, "get rssi para error\n");
+        return -FM_EPARA;
+    }
+
+    return 0;
+}
+
+static fm_s32 MT6620_Fast_SetFreq(fm_u16 freq)
+{
+    fm_s32 ret = 0;
+    fm_u16 pkt_size = 0;
+
+    if (FM_LOCK(cmd_buf_lock)) 
+               return (-FM_ELOCK);
+    pkt_size = mt6620_fast_tune(cmd_buf, TX_BUF_SIZE, freq);
+    ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_TUNE, SW_RETRY_CNT, SEEK_TIMEOUT, mt6620_get_read_result);
+    FM_UNLOCK(cmd_buf_lock);
+
+    if (ret) {
+        WCN_DBG(FM_ALT | CHIP, "mt6620_fast_tune failed\n");
+        return ret;
+    }
+    return ret;
+}
+
+/*
+ * mt6620_get_RSSI - set freq and return RSSI value
+*
+ */
+static fm_s32 mt6620_GetFreqCQI(fm_u16 freq,fm_s32 *pRSSI)
+{
+       if(MT6620_Fast_SetFreq(freq))
+       {
+               mt6620_GetCurRSSI(pRSSI);
+       }
+
+    return 0;
+}
+
+static fm_u8 mt6620_vol_tbl[16] = {
+    0, 1, 2, 3, 4, 5, 7, 9, 11, 14, 17, 21, 25, 30, 36, 43
+};
+static fm_s32 mt6620_SetVol(fm_u8 vol)
+{
+    fm_s32 ret = 0;
+    fm_u8 tmp_vol;// = vol & 0x3f;
+
+    vol = (vol > 15) ? 15 : vol;
+    tmp_vol = mt6620_vol_tbl[vol] & 0x3f;
+    if (tmp_vol > MT6620_VOL_MAX)
+        tmp_vol = MT6620_VOL_MAX;
+
+    ret = mt6620_set_bits(0x9C, (tmp_vol << 8), 0xC0FF);
+
+    if (ret) {
+        WCN_DBG(FM_ERR | CHIP, "Set vol=%d Failed\n", tmp_vol);
+        return ret;
+    } else {
+        WCN_DBG(FM_DBG | CHIP, "Set vol=%d OK\n", tmp_vol);
+    }
+
+    return 0;
+}
+
+static fm_s32 mt6620_GetVol(fm_u8 *pVol)
+{
+    fm_s32 ret = 0;
+    fm_u16 tmp_reg;
+
+    FMR_ASSERT(pVol);
+
+    ret = mt6620_read(0x9C, &tmp_reg);
+
+    if (ret) {
+        *pVol = 0;
+        WCN_DBG(FM_ERR | CHIP, "Get vol Failed\n");
+        return ret;
+    } else {
+        *pVol = (tmp_reg >> 8) & 0x3f;
+               if(*pVol == MT6620_VOL_MAX)
+                       *pVol = 15;
+               else
+                       *pVol = (*pVol/3);
+        WCN_DBG(FM_DBG | CHIP, "Get vol=%d OK\n", *pVol);
+    }
+
+    return 0;
+
+}
+
+static fm_s32 mt6620_dump_reg(void)
+{
+       fm_s32 i;
+       fm_u16 TmpReg;
+       for(i=0; i<0xff; i++)
+       {
+               mt6620_read(i, &TmpReg);
+               WCN_DBG(FM_NTC | CHIP, "0x%02x=0x%04x\n",i,TmpReg);
+       }
+       return 0;
+}
+
+
+static fm_bool mt6620_GetMonoStereo(fm_u16 *pMonoStereo)
+{
+    fm_u16 tmp_reg;
+
+    mt6620_write(FM_MAIN_PGSEL, 0x0001);
+
+    if (pMonoStereo) {
+        mt6620_read(0xF8, &tmp_reg);
+        *pMonoStereo = (tmp_reg & 0x0400) >> 10;
+    } else {
+        WCN_DBG(FM_ERR | CHIP, "MonoStero: para err\n");
+        return fm_false;
+    }
+
+    mt6620_write(FM_MAIN_PGSEL, 0x0000);
+
+    WCN_DBG(FM_DBG | CHIP, "MonoStero:0x%04x\n", *pMonoStereo);
+    return fm_true;
+}
+
+/*
+ * MT6620_SetMonoStereo
+ * Force set to stero/mono mode
+ * @MonoStereo -- 0, auto; 1, force mono
+ * If success, return 0; else error code
+ */
+static fm_s32 MT6620_SetMonoStereo(fm_s32 MonoStereo)
+{
+    fm_u16 tmp_reg;
+    fm_s32 ret = 0;
+    
+    if((ret = mt6620_write(FM_MAIN_PGSEL, FM_PG1)))
+        goto out;
+
+    tmp_reg = MonoStereo ? BITn(1) : 0; //MonoStereo, 1: force mono; 0:auto
+    if((ret = mt6620_set_bits(FM_STEROMONO_CTR, tmp_reg, MASK(1))))//set E0 D1=0
+        goto out;
+    
+    if((ret = mt6620_write(FM_MAIN_PGSEL, FM_PG0)))
+        goto out;
+    
+    WCN_DBG(FM_DBG | CHIP,"set to %s\n", MonoStereo ? "auto" : "force mono");
+    
+out:
+    return ret;
+}
+
+static fm_s32 mt6620_GetCapArray(fm_s32 *ca)
+{
+    fm_u16 dataRead;
+
+    FMR_ASSERT(ca);
+
+    mt6620_read(0x26, &dataRead);
+    *ca = dataRead;
+
+    return 0;
+}
+
+/*
+ * mt6620_GetCurPamd - get current freq's PAMD value
+ * PA=PAMD
+ * If PA>511 then PAMD(dB)=  (PA-1024)/16*6,
+ *                             else PAMD(dB)=PA/16*6
+ */
+static fm_bool mt6620_GetCurPamd(fm_u16 *pPamdLevl)
+{
+    fm_u16 tmp_reg;
+    fm_u16 dBvalue=0,valid_cnt=0;
+    fm_s32 i,total=0;
+
+    for (i = 0; i < 8; i++) 
+    {
+           if (mt6620_read(FM_ADDR_PAMD, &tmp_reg))
+           {
+               *pPamdLevl = 0;
+               return fm_false;
+               }
+
+           tmp_reg &= 0x00FF;
+           dBvalue = (tmp_reg>127) ? ((256-tmp_reg)*6/16):0;
+               if(dBvalue != 0)
+               {
+                       total += dBvalue;
+                       valid_cnt++;
+                       WCN_DBG(FM_DBG | CHIP, "[%d]PAMD=%d\n",i,dBvalue);
+               }
+        Delayms(3);
+       }
+       if(valid_cnt != 0)
+       {
+           *pPamdLevl = total/valid_cnt;
+       }
+       else
+       {
+               *pPamdLevl = 0;
+       }
+    WCN_DBG(FM_DBG | CHIP,"PamdLevl=%d\n", *pPamdLevl);
+    return fm_true;
+}
+
+static fm_s32 mt6620_ScanStop(void)
+{
+    return fm_force_active_event(FLAG_SCAN);
+}
+
+static fm_s32 mt6620_SeekStop(void)
+{
+    return fm_force_active_event(FLAG_SEEK);
+}
+
+/*
+ * mt6620_I2s_Setting - set the I2S state on MT6620
+ * @onoff - I2S on/off
+ * @mode - I2S mode: Master or Slave
+ *
+ * Return:0, if success; error code, if failed
+ */
+static fm_s32 mt6620_I2s_Setting(fm_s32 onoff, fm_s32 mode, fm_s32 sample)
+{
+    fm_u16 tmp_state = 0;
+    fm_u16 tmp_mode = 0;
+    fm_u16 tmp_sample = 0;
+    fm_s32 ret = 0;
+
+    if (onoff == MT6620_I2S_ON) {
+        tmp_state = 0x01; //I2S Frequency tracking on
+        mt6620_i2s_inf.status = 1;
+    } else if (onoff == MT6620_I2S_OFF) {
+        tmp_state = 0x00; //I2S Frequency tracking off
+        mt6620_i2s_inf.status = 0;
+    } else {
+        WCN_DBG(FM_ERR | CHIP, "%s():[onoff=%d]\n", __func__, onoff);
+        ret = -FM_EPARA;
+        goto out;
+    }
+
+    if (mode == MT6620_I2S_MASTER) {
+        tmp_mode = 0x03; //6620 as I2S master
+        mt6620_i2s_inf.mode = 1;
+    } else if (mode == MT6620_I2S_SLAVE) {
+        tmp_mode = 0x0B; //6620 as I2S slave
+        mt6620_i2s_inf.mode = 0;
+    } else {
+        WCN_DBG(FM_ERR | CHIP, "%s():[mode=%d]\n", __func__, mode);
+        ret = -FM_EPARA;
+        goto out;
+    }
+
+    if (sample == MT6620_I2S_32K) {
+        tmp_sample = 0x0000; //6620 I2S 32KHz sample rate
+        mt6620_i2s_inf.rate = 32000;
+    } else if (sample == MT6620_I2S_44K) {
+        tmp_sample = 0x0800; //6620 I2S 44.1KHz sample rate
+        mt6620_i2s_inf.rate = 44100;
+    } else if (sample == MT6620_I2S_48K) {
+        tmp_sample = 0x1000; //6620 I2S 48KHz sample rate
+        mt6620_i2s_inf.rate = 48000;
+    } else {
+        WCN_DBG(FM_ERR | CHIP, "%s():[sample=%d]\n", __func__, sample);
+        ret = -FM_EPARA;
+        goto out;
+    }
+
+    if ((ret = mt6620_set_bits(0x5F, tmp_sample, 0xE7FF)))
+        goto out;
+
+    if ((ret = mt6620_write(0x9B, tmp_mode)))
+        goto out;
+
+    if ((ret = mt6620_set_bits(0x56, tmp_state, 0xFF7F)))
+        goto out;
+
+    WCN_DBG(FM_NTC | CHIP, "[onoff=%s][mode=%s][sample=%d](0)33KHz,(1)44.1KHz,(2)48KHz\n",
+            (onoff == MT6620_I2S_ON) ? "On" : "Off",
+            (mode == MT6620_I2S_MASTER) ? "Master" : "Slave",
+            sample);
+out:
+    return ret;
+}
+static fm_s32 mt6620_Tx_Support(fm_s32 *sup)
+{
+       *sup=1;
+       return 0;
+}
+
+static fm_s32 mt6620_rdsTx_Support(fm_s32 *sup)
+{
+       *sup=1;
+       return 0;
+}
+
+static fm_s32 MT6620_FMOverBT(fm_bool enable)
+{
+    fm_s32 ret = 0;
+    static fm_u16 state = 0;
+    static fm_u16 mode = 0;
+    static fm_u16 sample = 0;
+    static fm_u16 inited = fm_false;
+
+    WCN_DBG(FM_NTC | CHIP,"+%s():\n", __func__);
+    if(inited == fm_false)
+    {
+        // record priv val
+        if((ret = mt6620_read(0x56, &state)))
+            goto out;
+        if((ret = mt6620_read(0x9B, &mode)))
+            goto out;
+        if((ret = mt6620_read(0x5F, &sample)))
+            goto out;
+        inited = fm_true;
+        WCN_DBG(FM_NTC | CHIP,"init, record priv seetings\n");
+    }
+    
+    if(enable == fm_true){
+        //disable analog output when FM over BT
+        if((ret = mt6620_set_bits(0x3A, 0, MASK(2))))
+            goto out;
+        //set FM over BT
+        if((ret = mt6620_write(0x56, 0x0001)))
+            goto out;
+        if((ret = mt6620_write(0x9B, 0x000b)))
+            goto out;
+        if((ret = mt6620_write(0x5F, 0x1175)))
+            goto out;
+        WCN_DBG(FM_NTC | CHIP,"set FM via BT controller\n");
+    }
+    else if(enable == fm_false)
+    {
+        //enable analog output when FM normal mode
+        if((ret = mt6620_set_bits(0x3A, BITn(2), MASK(2))))
+            goto out;
+        //recover to priv val
+        if((ret = mt6620_write(0x56, state)))
+            goto out;
+        if((ret = mt6620_write(0x9B, mode)))
+            goto out;
+        if((ret = mt6620_write(0x5F, sample)))
+            goto out;
+        WCN_DBG(FM_NTC | CHIP,"set FM via Host\n");
+    }
+    else
+    {
+        WCN_DBG(FM_ERR | CHIP,"%s()\n", __func__);
+        ret = -FM_EPARA;
+        goto out;
+    }
+out:
+    WCN_DBG(FM_NTC | CHIP,"-%s():[ret=%d]\n", __func__, ret);
+    return ret; 
+}
+
+/*fm soft mute tune function*/
+static fm_s32 mt6620_soft_mute_tune(fm_u16 freq,fm_s32 *rssi,fm_bool *valid)
+{
+    fm_s32 ret=0;
+    fm_u16 pkt_size;    
+    fm_s32 hilo_side = -1;    
+    struct mt6620_fm_softmute_tune_cqi_t *p_cqi;
+       fm_s32 RSSI=0, PAMD=0,MR=0, ATDC=0;
+       fm_u32 PRX=0;
+       fm_u16 softmuteGainLvl=0;
+
+       /*set hilo side first(f/w won't do this), need to check whether work if set before rampdown*/
+       if((ret = MT6620_HL_Side_Adj(freq, &hilo_side)))
+               return ret;
+       
+       if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK);
+       pkt_size = mt6620_full_cqi_req(cmd_buf, TX_BUF_SIZE, freq, 1, 1);
+       ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_SM_TUNE, SW_RETRY_CNT, SM_TUNE_TIMEOUT, mt6620_get_read_result);
+       FM_UNLOCK(cmd_buf_lock);
+
+       if (!ret && res) 
+       {
+               WCN_DBG(FM_NTC | CHIP, "smt cqi size %d\n", res->cqi[0]);
+               p_cqi = (struct mt6620_fm_softmute_tune_cqi_t*)&res->cqi[2];
+               // just for debug
+               WCN_DBG(FM_NTC | CHIP, "freq %d, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x\n", 
+                       p_cqi->ch, 
+                       p_cqi->rssi,
+                       p_cqi->pamd,
+                       p_cqi->mr,
+                       p_cqi->atdc,
+                       p_cqi->prx,
+                       p_cqi->smg); 
+               RSSI = ((p_cqi->rssi & 0x03FF) >= 512) ? ((p_cqi->rssi & 0x03FF) - 1024) : (p_cqi->rssi & 0x03FF);
+               PAMD = ((p_cqi->pamd & 0xFF) >= 128) ? ((p_cqi->pamd & 0x0FF) - 256) : (p_cqi->pamd & 0x0FF);
+               MR = ((p_cqi->mr & 0x01FF) >= 256) ? ((p_cqi->mr & 0x01FF) - 512) : (p_cqi->mr & 0x01FF);
+               ATDC =((p_cqi->atdc & 0x0FFF) >= 2048) ? ((p_cqi->atdc & 0x0FFF) - 4096) : (p_cqi->atdc & 0x0FFF);
+               if(ATDC < 0)
+               {
+                       ATDC = (~(ATDC)) - 1;//Get abs value of ATDC
+               }
+               PRX = (p_cqi->prx & 0x00FF);
+               softmuteGainLvl = p_cqi->smg;
+               //check if the channel is valid according to each CQIs
+               if((RSSI >= mt6620_fm_config.rx_cfg.long_ana_rssi_th) 
+                && (PAMD <= mt6620_fm_config.rx_cfg.pamd_th)
+                && (ATDC <= mt6620_fm_config.rx_cfg.atdc_th)
+                && (MR >= mt6620_fm_config.rx_cfg.mr_th)
+                && (PRX >= mt6620_fm_config.rx_cfg.prx_th)
+                && (softmuteGainLvl <= mt6620_fm_config.rx_cfg.smg_th))
+               {        
+                       *valid = fm_true;
+               }
+               else
+               {
+                       *valid = fm_false;
+               }
+               *rssi = RSSI;
+       }
+       else 
+       {
+               WCN_DBG(FM_ALT | CHIP, "smt get CQI failed\n");
+               return fm_false;
+       }
+       WCN_DBG(FM_NTC | CHIP, "valid=%d\n",*valid);
+       return fm_true;
+}
+static fm_s32 mt6620_i2s_info_get(fm_s32 *ponoff, fm_s32 *pmode, fm_s32 *psample)
+{
+    FMR_ASSERT(ponoff);
+    FMR_ASSERT(pmode);
+    FMR_ASSERT(psample);
+
+    *ponoff = mt6620_i2s_inf.status;
+    *pmode = mt6620_i2s_inf.mode;
+    *psample = mt6620_i2s_inf.rate;
+
+    return 0;
+}
+
+static fm_s32 mt6620_hw_info_get(struct fm_hw_info *req)
+{
+    FMR_ASSERT(req);
+
+    req->chip_id = mt6620_hw_info.chip_id;
+    req->eco_ver = mt6620_hw_info.eco_ver;
+    req->patch_ver = mt6620_hw_info.patch_ver;
+    req->rom_ver = mt6620_hw_info.rom_ver;
+
+    return 0;
+}
+
+static fm_bool mt6620_em_test(fm_u16 group_idx, fm_u16 item_idx, fm_u32 item_value)
+{
+       fm_s32 ret = 0;
+       
+       WCN_DBG(FM_NTC | CHIP,"+%s():[group_idx=%d],[item_idx=%d],[item_value=%d]\n", 
+               __func__, group_idx, item_idx, item_value);
+       
+       switch (group_idx){
+               case mono:
+                       if((ret = mt6620_write(FM_MAIN_PGSEL, 0x01)))
+                               goto out;
+
+                       if(item_value == 1){
+                               if((ret = mt6620_set_bits(0xE0, 0x02, 0xFFFF)))
+                                       goto out;
+                       }else{
+                               if((ret = mt6620_set_bits(0xE0, 0x0, 0xFFFD)))
+                                       goto out;
+                       }
+                       if((ret = mt6620_write(FM_MAIN_PGSEL, 0x0)))
+                               goto out;
+                       break;
+               case stereo:
+                       if((ret = mt6620_write(FM_MAIN_PGSEL, 0x01)))
+                               goto out;
+                       if(item_value == 0){
+                               if((ret = mt6620_set_bits(0xE0, 0x0, 0xFFFD)))
+                                       goto out;
+                       }else{
+                               switch (item_idx){
+                                       case Sblend_ON:
+                                               if((ret = mt6620_set_bits(0xD8, item_idx<<15, 0x7FFF)))
+                                                       goto out;
+                                               break;
+                                       case Sblend_OFF:
+                                               if((ret = mt6620_set_bits(0xD8, 0, 0x7FFF)))
+                                                       goto out;
+                                               break;
+                               }
+                       }
+                       if((ret = mt6620_write(FM_MAIN_PGSEL, 0x0)))
+                               goto out;
+                       break;
+               case RSSI_threshold:
+                       if((ret = mt6620_set_bits(0xe0, item_value, 0xFC00)))
+                               goto out;
+                       break;
+               case HCC_Enable:
+                       if((ret = mt6620_write(FM_MAIN_PGSEL, 0x01)))
+                               goto out;
+                       if(item_idx){
+                               if((ret = mt6620_set_bits(0xCF, 0x10, 0xFFFF)))
+                                       goto out;
+                       }else{
+                               if((ret = mt6620_set_bits(0xCF, 0x0, 0xFFEF)))
+                                       goto out;
+                       }
+                       if((ret = mt6620_write(FM_MAIN_PGSEL, 0x0)))
+                               goto out;
+                       break;
+               case PAMD_threshold:
+                       if((ret = mt6620_set_bits(0xE1, item_value, 0xFF00)))
+                               goto out;
+                       break;
+               case Softmute_Enable:
+                       if((ret = mt6620_write(FM_MAIN_PGSEL, 0x01)))
+                               goto out;
+                       if(item_idx){
+                               if((ret = mt6620_set_bits(0xCF, 0x0020, 0xFFFF))) //1:CF[5] = 1
+                                       goto out; 
+                       }else{
+                               if((ret = mt6620_set_bits(0xCF, 0x0000, 0xFFDF))) //1:CF[5] = 0
+                                       goto out; 
+                       }
+                       if((ret = mt6620_write(FM_MAIN_PGSEL, 0x0)))
+                               goto out;
+                       break;
+               case De_emphasis:
+                       if((ret = mt6620_write(FM_MAIN_PGSEL, 0x01)))
+                               goto out;
+                       if(item_idx == 2){
+                               if((ret = mt6620_set_bits(0xd4, 0x2000, 0xCFFF)))
+                                       goto out;
+                       }else if(item_idx == 1){
+                               if((ret = mt6620_set_bits(0xd4, 0x1000, 0xCFFF)))
+                                       goto out;
+                       }else if(item_idx == 0){
+                               if((ret = mt6620_set_bits(0xd4, 0x0000, 0xCFFF)))
+                                       goto out;
+                       }
+                       if((ret = mt6620_write(FM_MAIN_PGSEL, 0x0)))
+                               goto out;
+                       break;
+               case HL_Side:
+                       if(item_idx == 2){
+                                //H-Side
+                               if((ret = mt6620_set_bits(0xCB, 0x11, 0xFFFE)))
+                                       goto out;
+                               if((ret = mt6620_set_bits(0xF, 0x0400,  0xFBFF)))
+                                       goto out;
+                       }else if(item_idx == 1){
+                                //L-Side
+                               if((ret = mt6620_set_bits(0xCB, 0x10, 0xFFFE)))
+                                       goto out;
+                               if((ret = mt6620_set_bits(0xF, 0x0,  0xFBFF)))
+                                       goto out;
+                       }
+                       break;
+
+               case Dynamic_Limiter:
+                       if((ret = mt6620_write(FM_MAIN_PGSEL, 0x01)))
+                               goto out;
+                       if(item_idx){
+                               if((ret = mt6620_set_bits(0xFA, 0x0, 0xFFF7)))
+                                       goto out;
+                       }else{
+                               if((ret = mt6620_set_bits(0xFA, 0x08, 0xFFF7)))
+                                       goto out;
+                       }
+                       if((ret = mt6620_write(FM_MAIN_PGSEL, 0x0)))
+                               goto out;
+                       break;
+
+               case Softmute_Rate:
+                       if((ret = mt6620_write(FM_MAIN_PGSEL, 0x01)))
+                               goto out;
+                       if((ret = mt6620_set_bits(0xc8, item_value<<8, 0x80FF)))
+                               goto out;
+                       if((ret = mt6620_write(FM_MAIN_PGSEL, 0x0)))
+                               goto out;
+                       break;
+
+               case AFC_Enable:
+                       if (item_idx){
+                               if((ret = mt6620_set_bits(0x63, 0x0400, 0xFBFF)))
+                                       goto out;
+                       }else{
+                               if((ret = mt6620_set_bits(0x63, 0x0,    0xFBFF)))
+                                       goto out;
+                       }
+                       break;
+
+#if 0
+               case Softmute_Level:
+                       mt6620_write(FM_MAIN_PGSEL, 0x01);
+                       if(item_value > 0x24)
+                               item_value = 0x24;
+                       mt6620_set_bits(0xD1, item_value, 0xFFC0);
+                       mt6620_write(FM_MAIN_PGSEL, 0x0);
+                       break;
+#endif
+               case Analog_Volume:
+                       if((ret = mt6620_set_bits(0x9C, item_value<<8, 0xC0FF)))
+                               goto out;
+                       break;
+
+               default:
+                       break;
+       }
+
+out:
+       WCN_DBG(FM_NTC | CHIP,"-%s():[ret=%d]\n", __func__, ret);
+       return ret;
+return fm_true;
+}
+
+static const fm_u16 DesenseChMap[] = {
+    0x0000, 0x0000, 0x0000, 0x0000, /* 7675~7600, 7755~7680, 7835~7760, 7915~7840 */
+    0x0000, 0x0000, 0x0000, 0x0000, /* 7995~7920, 8075~8000, 8155~8080, 8235~8160 */
+    0x0000, 0x0000, 0x0000, 0x0000, /* 8315~8240, 8395~8320, 8475~8400, 8555~8480 */
+    0x0000, 0x0000, 0x0000, 0x0400, /* 8635~8560, 8715~8640, 8795~8720, 8875~8800 */
+    0x0000, 0x0000, 0x0000, 0x0000, /* 8955~8880, 9035~8960, 9115~9040, 9195~9120 */
+    0x00FC, 0x0000, 0x0000, 0x1C00, /* 9275~9200, 9355~9280, 9435~9360, 9515~9440 */
+    0x0000, 0x0001, 0x0000, 0x0000, /* 9595~9520, 9675~9600, 9755~9680, 9835~9760 */
+    0x0000, 0x7800, 0x0000, 0x0000, /* 9915~9840, 9995~9920, 10075~10000, 10155~10080 */
+    0x0000, 0x0000, 0x0000, 0x0000, /* 10235~10160, 10315~10240, 10395~10320, 10475~10400 */
+    0x0000, 0x0000, 0x0000, 0x0000, /* 10555~10480, 10635~10560, 10715~10640, 10795~10720 */
+    0x0000                          /* 10875~10800 */
+};
+// return value: 0, not a de-sense channel; 1, this is a de-sense channel; else error no
+static fm_s32 mt6620_is_dese_chan(fm_u16 freq)
+{
+       fm_u8 bDesenseCh = 0;
+
+    //caculate and applye compensation
+    if (0 == fm_get_channel_space(freq))
+    {
+        freq *= 10;
+    }
+       WCN_DBG(FM_NTC | CHIP,"%s, freq=%d\n",__func__,freq);
+    
+       bDesenseCh = ((0x0001 << (((freq - 7600)%80)/5)) & DesenseChMap[((freq - 7600)/80)])>>(((freq - 7600)%80)/5); 
+       WCN_DBG(FM_NTC | CHIP,"freq[%d] desense=[%d]\n",freq,bDesenseCh);
+
+    return bDesenseCh;
+}
+
+/*  return value:
+1, is desense channel and rssi is less than threshold; 
+0, not desense channel or it is but rssi is more than threshold.*/
+static fm_s32 mt6620_desense_check(fm_u16 freq,fm_s32 rssi)
+{
+       if(mt6620_is_dese_chan(freq))
+       {
+               if(rssi<mt6620_fm_config.rx_cfg.desene_rssi_th)
+               {
+                       return 1;
+               }
+       }
+    return 0;
+}
+static fm_s32 MT6620fm_low_power_wa_default(fm_s32 fmon)
+{
+    return 0;
+}
+
+fm_s32 MT6620fm_low_ops_register(struct fm_lowlevel_ops *ops)
+{
+    fm_s32 ret = 0;
+    //Basic functions.
+
+    FMR_ASSERT(ops);
+    FMR_ASSERT(ops->cb.cur_freq_get);
+    FMR_ASSERT(ops->cb.cur_freq_set);
+    fm_cb_op = &ops->cb;
+
+    ops->bi.low_pwr_wa = MT6620fm_low_power_wa_default;
+    ops->bi.pwron = mt6620_pwron;
+    ops->bi.pwroff = mt6620_pwroff;
+    ops->bi.msdelay = Delayms;
+    ops->bi.usdelay = Delayus;
+    ops->bi.read = mt6620_read;
+    ops->bi.write = mt6620_write;
+    ops->bi.setbits = mt6620_set_bits;
+    ops->bi.chipid_get = mt6620_get_chipid;
+    ops->bi.mute = mt6620_Mute;
+    ops->bi.rampdown = mt6620_RampDown;
+    ops->bi.pwrupseq = mt6620_PowerUp;
+    ops->bi.pwrdownseq = mt6620_PowerDown;
+    ops->bi.setfreq = mt6620_SetFreq;
+    ops->bi.seek = mt6620_Seek;
+    ops->bi.seekstop = mt6620_SeekStop;
+    ops->bi.scan = mt6620_Scan;
+    ops->bi.scanstop = mt6620_ScanStop;
+    ops->bi.rssiget = mt6620_GetCurRSSI;
+    ops->bi.volset = mt6620_SetVol;
+    ops->bi.volget = mt6620_GetVol;
+    ops->bi.dumpreg = mt6620_dump_reg;
+    ops->bi.msget = mt6620_GetMonoStereo;
+    ops->bi.msset = MT6620_SetMonoStereo;
+    ops->bi.pamdget = mt6620_GetCurPamd;
+    ops->bi.em = mt6620_em_test;
+    ops->bi.anaswitch = mt6620_SetAntennaType;
+    ops->bi.anaget = mt6620_GetAntennaType;
+    ops->bi.caparray_get = mt6620_GetCapArray;
+    ops->bi.i2s_set = mt6620_I2s_Setting;
+    ops->bi.i2s_get = mt6620_i2s_info_get;
+       ops->bi.is_dese_chan = mt6620_is_dese_chan;
+       ops->bi.softmute_tune = mt6620_soft_mute_tune;
+       ops->bi.desense_check = mt6620_desense_check;
+       ops->bi.get_freq_cqi = mt6620_GetFreqCQI;
+    ops->bi.hwinfo_get = mt6620_hw_info_get;
+    ops->bi.fm_via_bt = MT6620_FMOverBT;
+       /*****tx function****/
+       ops->bi.tx_support = mt6620_Tx_Support;
+       ops->bi.pwrupseq_tx = mt6620_PowerUpTx;
+       ops->bi.tune_tx = MT6620_SetFreq_Tx;
+       ops->bi.pwrdownseq_tx = mt6620_PowerDownTx;
+       ops->bi.tx_scan = mt6620_TxScan;
+    ops->ri.rds_tx = MT6620_Rds_Tx;
+    ops->ri.rds_tx_enable = MT6620_Rds_Tx_Enable;
+    ops->ri.rds_tx_disable = MT6620_Rds_Tx_Disable;
+    ops->ri.rdstx_support = mt6620_rdsTx_Support;
+    ops->bi.tx_pwr_ctrl = MT6620_TX_PWR_CTRL;
+    ops->bi.rtc_drift_ctrl = MT6620_RTC_Drift_CTRL;
+    ops->bi.tx_desense_wifi = MT6620_TX_DESENSE;
+
+       cmd_buf_lock = fm_lock_create("20_cmd");
+       ret = fm_lock_get(cmd_buf_lock);
+
+       cmd_buf = fm_zalloc(TX_BUF_SIZE + 1);
+
+       if (!cmd_buf) {
+               WCN_DBG(FM_ALT | CHIP, "6620 fm lib alloc tx buf failed\n");
+               ret = -1;
+       }
+
+#if 0//def MTK_FM_50KHZ_SUPPORT
+       cqi_fifo = fm_fifo_create("6620_cqi_fifo", sizeof(struct adapt_fm_cqi), 640);
+       if (!cqi_fifo) {
+               WCN_DBG(FM_ALT | CHIP, "6620 fm lib create cqi fifo failed\n");
+               ret = -1;
+       }
+#endif
+
+    return ret;
+}
+
+fm_s32 MT6620fm_low_ops_unregister(struct fm_lowlevel_ops *ops)
+{
+    fm_s32 ret = 0;
+    //Basic functions.
+#if 0//def MTK_FM_50KHZ_SUPPORT
+       fm_fifo_release(cqi_fifo);
+#endif
+       
+       if (cmd_buf) {
+               fm_free(cmd_buf);
+               cmd_buf = NULL;
+       }
+
+       ret = fm_lock_put(cmd_buf_lock);
+
+    FMR_ASSERT(ops);
+
+    fm_memset(&ops->bi, 0, sizeof(struct fm_basic_interface));
+    return ret;
+}
+
+
+/***********************************************************************
+*  Hi-Lo Side Injection
+*
+***********************************************************************/
+fm_s32 MT6620_HL_Side_Adj(fm_u16 freq, fm_s32 *hl)
+{
+    fm_s32 ret = 0;
+    fm_s32 isHiSide= 0;
+    fm_s32 tblsize = 0;
+    fm_s32 indx = 0;
+    fm_u16 tmp;
+    static fm_u16 Hi_Channels[] = {7950, 8070, 8210, 10640};
+
+    if (0 == fm_get_channel_space(freq)) {
+            freq *= 10;
+    }
+
+    WCN_DBG(FM_DBG | CHIP,"+%s, [freq=%d]\n", __func__, (fm_s32)freq);
+    
+    *hl = 0;
+    
+    if(sizeof(Hi_Channels) == 0)
+        goto out;
+    
+    tblsize = sizeof(Hi_Channels)/sizeof(Hi_Channels[0]);
+    for(indx = 0; indx < tblsize; indx++){
+        if(Hi_Channels[indx] == freq)
+        {
+            isHiSide = 1;
+            *hl = 1;
+            //goto set_HL;
+            break;
+        }     
+    }
+    
+    if(isHiSide){
+           //Set high-side injection (AFC)
+           if((ret = mt6620_read(0x0F, &tmp)))
+            goto out;
+           if((ret = mt6620_write(0x0F, tmp |0x0400)))
+            goto out;
+           if((ret = mt6620_write(FM_MAIN_PGSEL, 0)))
+            goto out;
+           //Set high-side injection (DFE)
+           if((ret = mt6620_read(0xCB, &tmp)))
+            goto out;
+           if((ret = mt6620_write(0xCB, tmp | 0x01)))
+            goto out;
+           //mt6620_write(0xCB, dataRead&0xFFFE);
+    }else{
+        //Set low-side injection (AFC)
+        if((ret = mt6620_read(0x0F, &tmp)))
+            goto out;
+           if((ret = mt6620_write(0x0F, tmp&0xFBFF)))
+            goto out;
+           if((ret = mt6620_write(FM_MAIN_PGSEL, 0)))
+            goto out;
+           //Set low-side injection (DFE)
+           if((ret = mt6620_read(0xCB, &tmp)))
+            goto out;
+           //mt6620_write(0xCB, dataRead | 0x01);
+        if((ret = mt6620_write(0xCB, tmp&0xFFFE)))
+            goto out;
+    }
+ out:   
+    WCN_DBG(FM_NTC | CHIP,"-%s, [isHiSide=%d][ret=%d]\n", __func__, (fm_s32)isHiSide, ret);
+    return ret;
+}
+
+/***********************************************************************
+*  ADPLL Power On or Off
+*
+***********************************************************************/
+fm_s32 MT6620_ADPLL_Power_OnOff(fm_s32 onoff, fm_s32 ADPLL_clk)
+{
+    fm_s32 ret = 0;
+
+    
+    switch(onoff){
+        case FM_ADPLL_ON:
+            if((ret = mt6620_write(0x25, 0x040F)))
+                goto out;
+            //Remove the Reset_N
+            if((ret = mt6620_write(0x20, 0x2720)))
+                goto out;
+            // change DLF loop gain  
+            // Set FMCR_DLF_GAIN_A = "9"
+            // Set FMCR_DLF_GAIN_B = "9"
+            if((ret = mt6620_write(0x22, 0x9980)))
+                goto out;
+            //Configure initial I_CODE for calibration
+            if((ret = mt6620_write(0x25, 0x080F)))
+                goto out;
+            //Enable ADPLL DCO
+            //Set FMCR_DCO_ EN = "1
+            if(ADPLL_clk == FM_ADPLL_16M){
+                if((ret = mt6620_write(0x1E, 0x0A63)))
+                    goto out;
+                // wait 5ms 
+                Delayms(5);
+                if((ret = mt6620_write(0x1E, 0x0A65)))
+                    goto out;
+                // wait 5ms 
+                Delayms(5);
+                if((ret = mt6620_write(0x1E, 0x0A71)))
+                    goto out;
+            }else if(ADPLL_clk == FM_ADPLL_15M){
+            if((ret = mt6620_write(0x1E, 0x0863)))
+                goto out;
+            // wait 5ms 
+            Delayms(5);
+            if((ret = mt6620_write(0x1E, 0x0865)))
+                goto out;
+            // wait 5ms 
+            Delayms(5);
+            if((ret = mt6620_write(0x1E, 0x0871)))
+                goto out;
+            }else{
+                ret = -FM_EPARA;
+                goto out;
+            }
+            // wait 100ms 
+            Delayms(100);
+            if((ret = mt6620_write(0x2A, 0x1026)))
+                goto out;
+            break;
+            
+        //ADPLL Power Off Sequence
+        case FM_ADPLL_OFF:
+            // Set rgfrf_top_ck = "0"
+            if((ret = mt6620_set_bits(0x2A, 0, MASK(12))))//set 2A D12=0
+                goto out;
+            // Set FMCR_OPEN_LOOP_EN = "0"
+            // Set FMCR_PLL_EN = "0"
+            // Set FMCR_DCO_EN = "0"
+            if((ret = mt6620_set_bits(0x1E, 0, MASK(7)&MASK(4)&MASK(0))))//set 1E D7 D4 D0=0
+                goto out;
+            // Set rgfrf_adpll_reset_n = "0"
+            if((ret = mt6620_set_bits(0x20, 0, MASK(13))))//set 20 D13=0
+                goto out;
+            // Set rgfrf_adpll_reset_n = "1"
+            if((ret = mt6620_set_bits(0x20, BITn(13), MASK(13))))//set 20 D13=1
+                goto out;
+            break;
+        default:
+            break;
+    }
+out:
+    return ret;
+}
+
+/***********************************************************************
+*  Frequency Avoidance
+*
+***********************************************************************/
+fm_s32 MT6620_ADPLL_Freq_Avoid(fm_u16 freq, fm_s32 *freqavoid)
+{
+    fm_s32 ret = 0;
+    fm_s32 ADPLL_clk = FM_ADPLL_15M;
+    fm_u16 dataRead = 0;
+    fm_u16 indx = 0;
+    static fm_u16 Avoid_Channels[] ={ 
+        7670, 7680, 7690, 7700, 8060, 8070, 8080, 8440, 8450, 8460, 8720, 8830, 8840, 9200,
+        9210, 9220, 9230, 9360, 9490, 9600, 9610, 9980, 9990, 10000, 10130, 10360, 10370, 10380, 10740,
+        10750, 10760, 10770
+    };
+
+    if (0 == fm_get_channel_space(freq)) {
+        freq *= 10;
+    }
+
+    WCN_DBG(FM_DBG | CHIP,"+%s, [freq=%d]\n", __func__, (fm_s32)freq);
+
+    *freqavoid = 0;
+    
+    dataRead = sizeof(Avoid_Channels)/sizeof(Avoid_Channels[0]);
+    indx = 0;
+    while((indx < dataRead) && (ADPLL_clk != FM_ADPLL_16M)){
+        if(Avoid_Channels[indx] == freq){
+            ADPLL_clk = FM_ADPLL_16M;
+            *freqavoid = 1;
+        }
+        indx++;
+    }
+    //isADPLL_16M = 1;
+    if((ret = mt6620_read(0x1E, &dataRead)))
+        goto out;
+    if(((dataRead&BITn(9))&&(ADPLL_clk == FM_ADPLL_16M))||(!(dataRead&BITn(9))&&(ADPLL_clk == FM_ADPLL_15M)))//1EH, D9
+        goto out; //we need not do freq avoid at these caes
+
+    if(ADPLL_clk == FM_ADPLL_16M){       
+        //Set rgf_f16mode_en = X       
+       if((ret = mt6620_set_bits(0x61, BITn(0), MASK(0))))//set 61H D0=1, 16.384MHZ
+                goto out;
+    }else if(ADPLL_clk == FM_ADPLL_15M){
+        //Set rgf_f16mode_en = X               
+       if((ret = mt6620_set_bits(0x61, 0, MASK(0))))//set 61H D0=0, 15.36MHZ
+                goto out;
+    }else{
+        ret = -FM_EPARA;
+        goto out;
+    } 
+    
+    // Disable ADPLL
+    ret = MT6620_ADPLL_Power_OnOff(FM_ADPLL_OFF, ADPLL_clk);
+    if(ret){
+        WCN_DBG(FM_NTC | CHIP,"%s, ADPLL OFF failed, [ret=%d]n", __func__, ret);
+        goto out;
+    }
+    
+    //Set FMCR_DCO_CK_SEL = ? (default = 0, 15.36)
+    if(ADPLL_clk == FM_ADPLL_16M){             
+        if((ret = mt6620_set_bits(0x1E, BITn(9), MASK(9))))//set 1EH D9=1, 16.384MHZ
+                goto out;
+    }else if(ADPLL_clk == FM_ADPLL_15M){
+        if((ret = mt6620_set_bits(0x1E, 0, MASK(9))))//set 1EH D9=0, 15.36MHZ
+                goto out;
+    }else{
+        ret = -FM_EPARA;
+        goto out;
+    }
+    
+    // Ensable ADPLL
+    ret = MT6620_ADPLL_Power_OnOff(FM_ADPLL_ON, ADPLL_clk);
+    if(ret){
+        WCN_DBG(FM_NTC | CHIP,"%s, ADPLL ON failed, [ret=%d]\n", __func__, ret);
+        goto out;
+    }
+    //Set rgfrf_cnt_resync_b = 0
+    if((ret = mt6620_set_bits(0x2A, 0, MASK(1))))//set 2AH D1=0
+        goto out;
+    //Set rgfrf_cnt_resync_b = 1
+    if((ret = mt6620_set_bits(0x2A, BITn(1), MASK(1))))//set 2AH D1=1
+        goto out; 
+out:
+    WCN_DBG(FM_NTC | CHIP,"-%s, [ADPLL_clk=%d][ret=%d]\n", __func__, (fm_s32)ADPLL_clk, ret);
+    return ret;
+}
+
+/***********************************************************************
+*  Frequency Avoidance
+*
+***********************************************************************/
+fm_s32 MT6620_MCU_Freq_Avoid(fm_u16 freq, fm_s32 *freqavoid)
+{
+    fm_s32 ret = 0;
+    fm_s32 mcuDsense = FM_MCU_DESE_DISABLE;
+    fm_u16 len = 0;
+    fm_u16 indx = 0;
+    static fm_u16 FreqList[] ={7800, 7940, 8320, 9260, 9600, 10400};
+
+    if (0 == fm_get_channel_space(freq)) {
+        freq *= 10;
+    }
+
+    WCN_DBG(FM_DBG | CHIP,"+%s, [freq=%d]\n", __func__, (fm_s32)freq);
+
+    *freqavoid = 0;
+    
+    len = sizeof(FreqList)/sizeof(FreqList[0]);
+    indx = 0;
+    while((indx < len) && (mcuDsense != FM_MCU_DESE_ENABLE)){
+        if(FreqList[indx] == freq){
+            mcuDsense = FM_MCU_DESE_ENABLE;
+            *freqavoid = 1;
+        }
+        indx++;
+    }
+
+       if(mcuDsense == FM_MCU_DESE_DISABLE){
+               if(mtk_wcn_wmt_dsns_ctrl(WMTDSNS_FM_DISABLE)){
+                       ret = 0;
+               }else{
+                       ret = -FM_ELINK;
+               }
+       }else if(mcuDsense == FM_MCU_DESE_ENABLE){
+               if(mtk_wcn_wmt_dsns_ctrl(WMTDSNS_FM_ENABLE)){
+                       ret = 0;
+               }else{
+                       ret = -FM_ELINK;
+               }
+       }else{
+               WCN_DBG(FM_ERR | CHIP,"para error!\n");
+               ret = -FM_EPARA;
+       }
+    
+    WCN_DBG(FM_NTC | CHIP,"-%s, [mcuDsense=%d][ret=%d]\n", __func__, (fm_s32)mcuDsense, ret);
+    return ret;
+}
+
+/***********************************************************************
+*  TX PWR CTRL
+*
+***********************************************************************/
+fm_s32 MT6620_TX_PWR_CTRL(fm_u16 freq, fm_s32 *ctr)
+{
+    #define MT6620_TX_PWR_LEV_MAX 120
+    #define MT6620_TX_PWR_LEV_MIN 85
+    fm_s32 ret = 0;
+    fm_s32 tmp = 0;
+    fm_u16 reg = 0;
+    fm_u16 coarse;
+    fm_u16 fine;
+    
+    WCN_DBG(FM_DBG | CHIP,"+%s, [freq=%d]\n", __func__, (fm_s32)freq);
+
+    if(freq < FM_TX_PWR_CTRL_FREQ_THR){
+        //Power setting - 1dB, 3C(HEX)=A9E9
+        *ctr -= 1;
+    }else{
+        //Power setting -2 dB, 3C(HEX)=A8E9
+        *ctr -= 2;
+    }
+    
+    if(*ctr > MT6620_TX_PWR_LEV_MAX){
+        *ctr = MT6620_TX_PWR_LEV_MAX;
+    }else if(*ctr < MT6620_TX_PWR_LEV_MIN){
+        *ctr = MT6620_TX_PWR_LEV_MIN;
+    }
+    fine = 43017 + ((1<<((*ctr-85)%6))-1)*32;
+    WCN_DBG(FM_DBG | CHIP,"0x3C = 0x%04x \n", fine);
+    coarse = 514 + ((1<<((*ctr-85)/6))-1)*4;
+    WCN_DBG(FM_DBG | CHIP,"0x3D = 0x%04x \n", coarse);
+    
+    if((ret = mt6620_write(0x3C, fine)))
+            goto out;
+    if((ret = mt6620_write(0x3D, coarse)))
+            goto out;
+
+    tmp = mtk_wcn_wmt_therm_ctrl(WMTTHERM_READ);
+    if((ret = mt6620_read(0x9C, &reg)))
+        goto out;
+    reg &= 0xC0FF;
+    if(tmp < FM_TX_PWR_CTRL_TMP_THR_DOWN){
+        reg |= (0x1C << 8);  //9CH, D13~D8 = 1C
+    }else if(tmp > FM_TX_PWR_CTRL_TMP_THR_UP){
+        reg |= (0x33 << 8);  //9CH, D13~D8 ==33
+    }else{
+        reg |= (0x25 << 8);  //9CH, D13~D8 =25
+    }
+    if((ret = mt6620_write(0x9C, reg)))
+        goto out;
+
+out:
+    WCN_DBG(FM_NTC | CHIP,"-%s, [temp=%d][ret=%d]\n", __func__, (fm_s32)tmp, ret);
+    return ret;
+}
+
+/***********************************************************************
+*  TX RTC PWR CTRL
+*
+***********************************************************************/
+fm_s32 MT6620_RTC_Drift_CTRL(fm_u16 freq, fm_s32 *ctr)
+{
+    fm_s32 ret = 0;
+    fm_u16 reg = 0;
+    fm_s32 chanel_resolution = 1;
+    fm_s16 compensation_int16 = 0;
+    fm_s32 tmp = 0;
+    fm_s32 drift = *ctr;
+    
+    WCN_DBG(FM_DBG | CHIP,"+%s, [freq=%d]\n", __func__, (fm_s32)freq);
+
+    //turn off VCO tracking
+    if((ret = mt6620_set_bits(0x48, 0, MASK(15))))//set 48 D15=0
+        goto out;
+    
+    //get channel resolution
+    if((ret = mt6620_read(0x46, &reg)))
+        goto out;
+    reg &= 0xC000;
+    switch(reg >> 14){
+        case 0:
+            chanel_resolution = 1024;
+            break;
+        case 1:
+            chanel_resolution = 512;
+            break;
+        case 2:
+            chanel_resolution = 256;
+            break;
+        case 3:
+            chanel_resolution = 128;
+            break;
+        default:
+            WCN_DBG(FM_ERR | CHIP,"chanel_resolution error[%d]\n", (fm_s32)(reg >> 14));
+            break;
+    }
+
+    //caculate and applye compensation
+    if (0 == fm_get_channel_space(freq)) {
+        freq *= 10;
+    }
+    WCN_DBG(FM_DBG | CHIP,"[resolution=%d][freq=%d][drift=%d]\n", chanel_resolution, (fm_s32)(freq/100), (*ctr));
+    tmp = (2*drift*(freq/100))/chanel_resolution;
+    compensation_int16 = (fm_s16)tmp;
+    if(compensation_int16 >= 511){
+        compensation_int16 = 511;
+    }else if(compensation_int16 <= -512){
+        compensation_int16 = -512;
+    }
+    if((ret = mt6620_read(0x47, &reg)))
+        goto out;
+    reg &= 0x003F;
+    reg |= (compensation_int16 << 6);
+    if((ret = mt6620_write(0x47, reg)))
+        goto out;
+
+    /*
+    //turn on VCO tracking
+    if((ret = mt6620_set_bits(0x48, BITn(15), MASK(15))))//set 48 D15=1
+        goto out;
+        */
+out:
+    WCN_DBG(FM_NTC | CHIP,"-%s, [compensation=%d][ret=%d]\n", __func__, (fm_s32)(compensation_int16), ret);
+    return ret;
+}
+
+/***********************************************************************
+*  TX desense with WIFI/BT
+*
+***********************************************************************/
+fm_s32 MT6620_TX_DESENSE(fm_u16 freq, fm_s32 *ctr)
+{
+    fm_s32 ret = 0;
+    fm_u16 dataRead = 0;
+    fm_u16 tmp = 0;
+    
+    WCN_DBG(FM_DBG|CHIP,"+%s, [freq=%d]\n", __func__, (fm_s32)freq);
+
+    // enable FM TX VCO tracking
+    if((ret = mt6620_read(0x29, &dataRead)))//read 29 
+        goto out;
+    WCN_DBG(FM_NTC | CHIP,"Before VCO On, [0x29=0x%04x]\n", dataRead);
+    if((ret = mt6620_read(0x12, &dataRead)))//read 12 
+        goto out;
+    WCN_DBG(FM_NTC | CHIP,"Before VCO On, [0x12=0x%04x]\n", dataRead);
+    
+    if((ret = mt6620_set_bits(0x12, 0, MASK(15))))//set 12 D15=0
+        goto out;
+    if((ret = mt6620_set_bits(0x41, BITn(0), MASK(0))))//set 41 D0=1
+        goto out;
+    if((ret = mt6620_set_bits(0x48, BITn(15), MASK(15))))//set 48 D15=1
+        goto out;
+
+    // wait 100ms (VCO tracking 100ms)
+    if(*ctr > FM_TX_TRACKING_TIME_MAX){
+        *ctr = FM_TX_TRACKING_TIME_MAX;
+    }
+    Delayms(*ctr);
+
+    // disable FM TX VCO tracking
+    if((ret = mt6620_set_bits(0x28, BITn(2), MASK(2))))//set 28 D2=1
+        goto out;
+    if((ret = mt6620_read(0x29, &dataRead)))//read 29 D11~D0
+        goto out;
+    WCN_DBG(FM_NTC | CHIP,"Before VCO Off, [0x29=0x%04x]\n", dataRead);
+    tmp = dataRead&0x0FFF; // Read 0x29 D11~D0
+    if((ret = mt6620_read(0x12, &dataRead)))//read 12 
+        goto out;
+    //Set 0x12 D15 to 1, D11:D0 to read(0x29 D11~D0)
+    dataRead &= 0xF000; 
+    dataRead |= tmp;
+    dataRead |= 1<<15;
+    if((ret = mt6620_write(0x12, dataRead)))
+        goto out;
+    WCN_DBG(FM_NTC | CHIP,"Before VCO Off, [0x12=0x%04x]\n", dataRead);
+    if((ret = mt6620_set_bits(0x48, 0, MASK(15))))//set 48 D15=0
+        goto out;
+    if((ret = mt6620_set_bits(0x41, 0, MASK(0))))//set 41 D0=0
+        goto out;
+    
+out:
+    WCN_DBG(FM_DBG | CHIP,"-%s, [freq=%d][delay=%dms][ret=%d]\n", __func__, (fm_s32)freq, *ctr, ret);
+    return ret;
+}
+
+static fm_s32 MT6620_Rds_Tx_Enable(void)
+{
+       mt6620_write(0x9F, 0x0000);
+       mt6620_write(0xAB, 0x3872);
+       mt6620_write(0xAC, 0x3B3A);
+       mt6620_write(0xAD, 0x0113);
+       mt6620_write(0xAE, 0x03B2);
+       mt6620_write(0xAF, 0x0001);
+       mt6620_write(0xB1, 0x63EB);
+       mt6620_write(0xF4, 0x0020);
+       mt6620_write(0xF5, 0x3222);
+
+    return 0;
+}
+
+static fm_s32 MT6620_Rds_Tx_Disable(void)
+{
+       mt6620_write(0x9F, 0x0000);
+       mt6620_write(0xAB, 0x39B6);
+       mt6620_write(0xAC, 0x3C3E);
+       mt6620_write(0xAD, 0x0000);
+       mt6620_write(0xAE, 0x03C2);
+       mt6620_write(0xAF, 0x0001);
+       mt6620_write(0xF4, 0x0020);
+       mt6620_write(0xF5, 0xBF16);
+       mt6620_write(0xB1, 0x623D);
+
+    return 0;
+}
+
+static fm_s32 MT6620_Rds_Tx(fm_u16 pi, fm_u16 *ps, fm_u16 *other_rds, fm_u8 other_rds_cnt)
+{
+    fm_s32 ret = 0;
+    fm_u16 pkt_size = 0;
+
+       WCN_DBG(FM_NTC | RDSC, "+%s():PI=0x%04x, PS=0x%04x/0x%04x/0x%04x, other_rds_cnt=%d \n",__func__, pi, ps[0], ps[1], ps[2], other_rds_cnt);
+    if (FM_LOCK(cmd_buf_lock)) 
+               return (-FM_ELOCK);
+    pkt_size = mt6620_rds_tx(cmd_buf, TX_BUF_SIZE, pi, ps, other_rds, other_rds_cnt);
+    ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_RDS_TX, SW_RETRY_CNT, RDS_TX_TIMEOUT, NULL);
+    FM_UNLOCK(cmd_buf_lock);
+        
+    return ret;
+}
+
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6620/pub/mt6620_fm_link.c b/drivers/mtk_wcn_combo/drv_fm/mt6620/pub/mt6620_fm_link.c
new file mode 100755 (executable)
index 0000000..48ddd35
--- /dev/null
@@ -0,0 +1,470 @@
+/* mt6620_fm_link.c
+ *
+ * (C) Copyright 2011
+ * MediaTek <www.MediaTek.com>
+ * Hongcheng <hongcheng.xia@MediaTek.com>
+ *
+ * MT6620 FM Radio Driver -- setup data link
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#if 0
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+
+#include "stp_exp.h"
+#include "wmt_exp.h"
+
+#include "fm_typedef.h"
+#include "fm_dbg.h"
+#include "fm_err.h"
+#include "fm_stdlib.h"
+
+#include "mt6620_fm.h"
+#include "mt6620_fm_link.h"
+static struct fm_link_event *link_event;
+
+static struct fm_trace_fifo_t *cmd_fifo;
+
+static struct fm_trace_fifo_t *evt_fifo;
+    
+static fm_s32 (*reset)(fm_s32 sta) = NULL;
+
+static void mt6620_fm_wholechip_rst_cb(ENUM_WMTDRV_TYPE_T src,
+                                ENUM_WMTDRV_TYPE_T dst,
+                                ENUM_WMTMSG_TYPE_T type,
+                                void *buf,
+                                unsigned int sz)
+{
+    //To handle reset procedure please
+    ENUM_WMTRSTMSG_TYPE_T rst_msg;
+    
+    if (sz <= sizeof(ENUM_WMTRSTMSG_TYPE_T)) {
+        memcpy((char *)&rst_msg, (char *)buf, sz);
+        WCN_DBG(FM_WAR | LINK, "[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_FM) && (type == WMTMSG_TYPE_RESET)) {
+            if (rst_msg == WMTRSTMSG_RESET_START) {
+                WCN_DBG(FM_WAR | LINK, "FM restart start!\n");
+                if (reset) {
+                    reset(1);
+                }
+                
+            } else if (rst_msg == WMTRSTMSG_RESET_END) {
+                WCN_DBG(FM_WAR | LINK, "FM restart end!\n");
+                if (reset) {
+                    reset(0);
+                }
+            }
+        }
+    } else {
+        /*message format invalid*/
+        WCN_DBG(FM_WAR | LINK, "message format invalid!\n");
+    }
+}
+
+    
+fm_s32 fm_link_setup(void* data)
+{
+    fm_s32 ret = 0;
+    
+    if (!(link_event = fm_zalloc(sizeof(struct fm_link_event)))) {
+        WCN_DBG(FM_ALT | LINK, "fm_zalloc(fm_link_event) -ENOMEM\n");
+        return -1;
+    }
+
+    link_event->ln_event = fm_flag_event_create("ln_evt");
+
+    if (!link_event->ln_event) {
+        WCN_DBG(FM_ALT | LINK, "create mt6620_ln_event failed\n");
+        fm_free(link_event);
+        return -1;
+    }
+
+    fm_flag_event_get(link_event->ln_event);
+
+
+    WCN_DBG(FM_NTC | LINK, "fm link setup\n");
+
+    cmd_fifo = fm_trace_fifo_create("cmd_fifo");
+    if (!cmd_fifo) {
+        WCN_DBG(FM_ALT | LINK, "create cmd_fifo failed\n");
+        ret = -1;
+        goto failed;
+    }
+    
+    evt_fifo = fm_trace_fifo_create("evt_fifo");
+    if (!evt_fifo) {
+        WCN_DBG(FM_ALT | LINK, "create evt_fifo failed\n");
+        ret = -1;
+        goto failed;
+    }
+    
+    reset = data; // get whole chip reset cb
+    mtk_wcn_wmt_msgcb_reg(WMTDRV_TYPE_FM, mt6620_fm_wholechip_rst_cb);
+    return 0;
+    
+failed:
+    fm_trace_fifo_release(evt_fifo);
+    fm_trace_fifo_release(cmd_fifo);
+    fm_flag_event_put(link_event->ln_event);
+    if (link_event) {
+        fm_free(link_event);
+    }
+    
+    return ret;
+}
+
+fm_s32 fm_link_release(void)
+{
+
+    fm_trace_fifo_release(evt_fifo);
+    fm_trace_fifo_release(cmd_fifo);
+    fm_flag_event_put(link_event->ln_event);
+    if (link_event) {
+        fm_free(link_event);
+    }
+
+    WCN_DBG(FM_NTC | LINK, "fm link release\n");
+    return 0;
+}
+
+/*
+ * fm_ctrl_rx
+ * the low level func to read a rigister
+ * @addr - rigister address
+ * @val - the pointer of target buf
+ * If success, return 0; else error code
+ */
+fm_s32 fm_ctrl_rx(fm_u8 addr, fm_u16 *val)
+{
+    return 0;
+}
+
+/*
+ * fm_ctrl_tx
+ * the low level func to write a rigister
+ * @addr - rigister address
+ * @val - value will be writed in the rigister
+ * If success, return 0; else error code
+ */
+fm_s32 fm_ctrl_tx(fm_u8 addr, fm_u16 val)
+{
+    return 0;
+}
+
+/*
+ * fm_cmd_tx() - send cmd to FM firmware and wait event
+ * @buf - send buffer
+ * @len - the length of cmd
+ * @mask - the event flag mask
+ * @   cnt - the retry conter
+ * @timeout - timeout per cmd
+ * Return 0, if success; error code, if failed
+ */
+fm_s32 fm_cmd_tx(fm_u8* buf, fm_u16 len, fm_s32 mask, fm_s32 cnt, fm_s32 timeout, fm_s32(*callback)(struct fm_res_ctx* result))
+{
+    fm_s32 ret_time = 0;
+    struct task_struct *task = current;
+    struct fm_trace_t trace;
+
+    if ((NULL == buf) || (len < 0) || (0 == mask)
+            || (cnt > SW_RETRY_CNT_MAX) || (timeout > SW_WAIT_TIMEOUT_MAX)) {
+        WCN_DBG(FM_ERR | LINK, "cmd tx, invalid para\n");
+        return -FM_EPARA;
+    }
+
+    FM_EVENT_CLR(link_event->ln_event, mask);
+    
+#ifdef FM_TRACE_ENABLE
+    trace.type = buf[0];
+    trace.opcode = buf[1];
+    trace.len = len - 4;
+    trace.tid = (fm_s32)task->pid;
+    fm_memset(trace.pkt, 0, FM_TRACE_PKT_SIZE);
+    fm_memcpy(trace.pkt, &buf[4], (trace.len > FM_TRACE_PKT_SIZE) ? FM_TRACE_PKT_SIZE : trace.len);
+#endif
+
+sw_retry:
+
+#ifdef FM_TRACE_ENABLE
+    if (fm_true == FM_TRACE_FULL(cmd_fifo)) {
+        FM_TRACE_OUT(cmd_fifo, NULL);
+    }
+    FM_TRACE_IN(cmd_fifo, &trace);
+#endif
+
+    //send cmd to FM firmware
+    if (mtk_wcn_stp_send_data(buf, len, FM_TASK_INDX) <= 0) {
+        WCN_DBG(FM_EMG | LINK, "send data over stp failed\n");
+        return -FM_ELINK;
+    }
+
+    //wait the response form FM firmware
+    ret_time = FM_EVENT_WAIT_TIMEOUT(link_event->ln_event, mask, timeout);
+
+    if (!ret_time) {
+        if (0 < cnt--) {
+            WCN_DBG(FM_WAR | LINK, "wait even timeout, [retry_cnt=%d], pid=%d\n", cnt, task->pid);
+            fm_print_cmd_fifo();
+            fm_print_evt_fifo();
+            return -FM_EFW;
+            goto sw_retry; //retry if timeout and retry cnt > 0
+        } else {
+            WCN_DBG(FM_ALT | LINK, "fatal error, SW retry failed, reset HW\n");
+            return -FM_EFW;
+        }
+    }
+
+    FM_EVENT_CLR(link_event->ln_event, mask);
+
+    if (callback) {
+        callback(&link_event->result);
+    }
+
+    return 0;
+}
+
+fm_s32 fm_event_parser(fm_s32(*rds_parser)(struct rds_rx_t*, fm_s32))
+{
+    fm_s32 len;
+    fm_s32 i = 0;
+    fm_u8 opcode = 0;
+    fm_u16 length = 0;
+    fm_u8 ch;
+    fm_u8 rx_buf[RX_BUF_SIZE + 10] = {0}; //the 10 bytes are protect gaps
+    static volatile fm_task_parser_state state = FM_TASK_RX_PARSER_PKT_TYPE;
+    struct fm_trace_t trace;
+    struct task_struct *task = current;
+
+    len = mtk_wcn_stp_receive_data(rx_buf, RX_BUF_SIZE, FM_TASK_INDX);
+    WCN_DBG(FM_DBG | LINK, "[len=%d],[CMD=0x%02x 0x%02x 0x%02x 0x%02x]\n", len, rx_buf[0], rx_buf[1], rx_buf[2], rx_buf[3]);
+
+    while (i < len) {
+        ch = rx_buf[i];
+
+        switch (state) {
+        case FM_TASK_RX_PARSER_PKT_TYPE:
+
+            if (ch == FM_TASK_EVENT_PKT_TYPE) {
+                if ((i + 5) < RX_BUF_SIZE) {
+                    WCN_DBG(FM_DBG | LINK, "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x \n", rx_buf[i], rx_buf[i+1], rx_buf[i+2], rx_buf[i+3], rx_buf[i+4], rx_buf[i+5]);
+                } else {
+                    WCN_DBG(FM_DBG | LINK, "0x%02x 0x%02x\n", rx_buf[i], rx_buf[i+1]);
+                }
+
+                state = FM_TASK_RX_PARSER_OPCODE;
+            } else {
+                WCN_DBG(FM_ALT | LINK, "event pkt type error (rx_buf[%d] = 0x%02x)\n", i, ch);
+            }
+
+            i++;
+            break;
+
+        case FM_TASK_RX_PARSER_OPCODE:
+            i++;
+            opcode = ch;
+            state = FM_TASK_RX_PARSER_PKT_LEN_1;
+            break;
+
+        case FM_TASK_RX_PARSER_PKT_LEN_1:
+            i++;
+            length = ch;
+            state = FM_TASK_RX_PARSER_PKT_LEN_2;
+            break;
+
+        case FM_TASK_RX_PARSER_PKT_LEN_2:
+            i++;
+            length |= (fm_u16)(ch << 0x8);
+
+#ifdef FM_TRACE_ENABLE
+            trace.type = FM_TASK_EVENT_PKT_TYPE;
+            trace.opcode = opcode;
+            trace.len = length;
+            trace.tid = (fm_s32)task->pid;
+            fm_memset(trace.pkt, 0, FM_TRACE_PKT_SIZE);
+            fm_memcpy(trace.pkt, &rx_buf[i], (length > FM_TRACE_PKT_SIZE) ? FM_TRACE_PKT_SIZE : length);
+
+            if (fm_true == FM_TRACE_FULL(cmd_fifo)) {
+                FM_TRACE_OUT(cmd_fifo, NULL);
+            }
+            FM_TRACE_IN(cmd_fifo, &trace);
+#endif
+            if (length > 0) {
+                state = FM_TASK_RX_PARSER_PKT_PAYLOAD;
+            } else {
+                state = FM_TASK_RX_PARSER_PKT_TYPE;
+                FM_EVENT_SEND(link_event->ln_event, (1 << opcode));
+            }
+
+            break;
+
+        case FM_TASK_RX_PARSER_PKT_PAYLOAD:
+
+            switch (opcode) {
+            case FM_TUNE_OPCODE:
+
+                if ((length == 1) && (rx_buf[i] == 1)) {
+                    FM_EVENT_SEND(link_event->ln_event, FLAG_TUNE_DONE);
+                }
+
+                break;
+
+            case FM_SOFT_MUTE_TUNE_OPCODE:
+
+                if (length >= 2) {
+                    fm_memcpy(link_event->result.cqi, &rx_buf[i], (length > FM_CQI_BUF_SIZE) ? FM_CQI_BUF_SIZE : length);
+                    FM_EVENT_SEND(link_event->ln_event, FLAG_SM_TUNE);
+                }
+                break;
+                
+            case FM_SEEK_OPCODE:
+
+                if ((i + 1) < RX_BUF_SIZE) {
+                    link_event->result.seek_result = rx_buf[i] + (rx_buf[i+1] << 8); // 8760 means 87.60Mhz
+                }
+
+                FM_EVENT_SEND(link_event->ln_event, FLAG_SEEK_DONE);
+                break;
+
+            case FM_SCAN_OPCODE:
+
+                //check if the result data is long enough
+                if ((RX_BUF_SIZE - i) < (sizeof(fm_u16) * FM_SCANTBL_SIZE)) {
+                    WCN_DBG(FM_ALT | LINK, "FM_SCAN_OPCODE err, [tblsize=%d],[bufsize=%d]\n", (sizeof(fm_u16) * FM_SCANTBL_SIZE), (RX_BUF_SIZE - i));
+                    FM_EVENT_SEND(link_event->ln_event, FLAG_SCAN_DONE);
+                    return 0;
+                } else if ((length >= FM_CQI_BUF_SIZE) && ((RX_BUF_SIZE - i) >= FM_CQI_BUF_SIZE)) {
+                    fm_memcpy(link_event->result.cqi, &rx_buf[i], FM_CQI_BUF_SIZE);
+                    FM_EVENT_SEND(link_event->ln_event, FLAG_CQI_DONE);
+                } else {
+                    fm_memcpy(link_event->result.scan_result, &rx_buf[i], sizeof(fm_u16) * FM_SCANTBL_SIZE);
+                    FM_EVENT_SEND(link_event->ln_event, FLAG_SCAN_DONE);
+                }
+
+                break;
+
+            case FSPI_READ_OPCODE:
+
+                if ((i + 1) < RX_BUF_SIZE) {
+                    link_event->result.fspi_rd = (rx_buf[i] + (rx_buf[i+1] << 8));
+                }
+
+                FM_EVENT_SEND(link_event->ln_event, (1 << opcode));
+                break;
+
+            case RDS_RX_DATA_OPCODE:
+
+                //check if the rds data is long enough
+                if ((RX_BUF_SIZE - i) < length) {
+                    WCN_DBG(FM_ALT | LINK, "RDS RX err, [rxlen=%d],[bufsize=%d]\n", (fm_s32)length, (RX_BUF_SIZE - i));
+                    FM_EVENT_SEND(link_event->ln_event, (1 << opcode));
+                    break;
+                }
+
+                //copy rds data to rds buf
+                fm_memcpy(&link_event->result.rds_rx_result, &rx_buf[i], length);
+
+                /*Handle the RDS data that we get*/
+                if (rds_parser) {
+                    rds_parser(&link_event->result.rds_rx_result, length);
+                } else {
+                    WCN_DBG(FM_WAR | LINK, "no method to parse RDS data\n");
+                }
+
+                FM_EVENT_SEND(link_event->ln_event, (1 << opcode));
+                break;
+
+            default:
+                FM_EVENT_SEND(link_event->ln_event, (1 << opcode));
+                break;
+            }
+
+            state = FM_TASK_RX_PARSER_PKT_TYPE;
+            i += length;
+            break;
+
+        default:
+            break;
+        }
+    }
+
+    return 0;
+}
+
+fm_bool fm_wait_stc_done(fm_u32 sec)
+{
+    return fm_true;
+}
+
+fm_s32 fm_force_active_event(fm_u32 mask)
+{
+    fm_u32 flag;
+
+    flag = FM_EVENT_GET(link_event->ln_event);
+    WCN_DBG(FM_WAR | LINK, "before force active event, [flag=0x%08x]\n", flag);
+    flag = FM_EVENT_SEND(link_event->ln_event, mask);
+    WCN_DBG(FM_WAR | LINK, "after force active event, [flag=0x%08x]\n", flag);
+
+    return 0;
+}
+
+
+extern fm_s32 fm_print_cmd_fifo(void)
+{
+#ifdef FM_TRACE_ENABLE
+    struct fm_trace_t trace;
+    fm_s32 i = 0;
+    
+    while (fm_false == FM_TRACE_EMPTY(cmd_fifo)) {
+        fm_memset(trace.pkt, 0, FM_TRACE_PKT_SIZE);
+        FM_TRACE_OUT(cmd_fifo, &trace);
+        WCN_DBG(FM_ALT | LINK, "trace, type %d, op %d, len %d, tid %d, time %d\n", trace.type, trace.opcode, trace.len, trace.tid, jiffies_to_msecs(abs(trace.time)));
+        i = 0;
+        while ((trace.len > 0) && (i < trace.len) && (i < (FM_TRACE_PKT_SIZE-8))) {
+            WCN_DBG(FM_ALT | LINK, "trace, %02x %02x %02x %02x %02x %02x %02x %02x\n", \
+                trace.pkt[i], trace.pkt[i+1], trace.pkt[i+2], trace.pkt[i+3], trace.pkt[i+4], trace.pkt[i+5], trace.pkt[i+6], trace.pkt[i+7]);
+            i += 8;
+        }
+        WCN_DBG(FM_ALT | LINK, "trace\n");
+    }
+#endif
+
+    return 0;
+}
+
+extern fm_s32 fm_print_evt_fifo(void)
+{
+#ifdef FM_TRACE_ENABLE
+    struct fm_trace_t trace;
+    fm_s32 i = 0;
+    
+    while (fm_false == FM_TRACE_EMPTY(evt_fifo)) {
+        fm_memset(trace.pkt, 0, FM_TRACE_PKT_SIZE);
+        FM_TRACE_OUT(evt_fifo, &trace);
+        WCN_DBG(FM_ALT | LINK, "%s: op %d, len %d, %d\n", evt_fifo->name, trace.opcode, trace.len, jiffies_to_msecs(abs(trace.time)));
+        i = 0;
+        while ((trace.len > 0) && (i < trace.len) && (i < (FM_TRACE_PKT_SIZE-8))) {
+            WCN_DBG(FM_ALT | LINK, "%s: %02x %02x %02x %02x %02x %02x %02x %02x\n", \
+                evt_fifo->name, trace.pkt[i], trace.pkt[i+1], trace.pkt[i+2], trace.pkt[i+3], trace.pkt[i+4], trace.pkt[i+5], trace.pkt[i+6], trace.pkt[i+7]);
+            i += 8;
+        }
+        WCN_DBG(FM_ALT | LINK, "%s\n", evt_fifo->name);
+    }
+#endif
+
+    return 0;
+}
+#endif
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6620/pub/mt6620_fm_rds.c b/drivers/mtk_wcn_combo/drv_fm/mt6620/pub/mt6620_fm_rds.c
new file mode 100755 (executable)
index 0000000..27e5729
--- /dev/null
@@ -0,0 +1,363 @@
+/* mt6620_rds.c
+ *
+ * (C) Copyright 2011
+ * MediaTek <www.MediaTek.com>
+ * hongcheng <hongcheng.xia@MediaTek.com>
+ *
+ * mt6620 FM Radio Driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include "fm_typedef.h"
+#include "fm_dbg.h"
+#include "fm_err.h"
+#include "fm_interface.h"
+#include "fm_stdlib.h"
+#include "fm_rds.h"
+#include "mt6620_fm_reg.h"
+
+
+#define MT6620_RDS_BLER_TH1 90
+#define MT6620_RDS_BLER_TH2 60
+#define MT6620_RDS_BLER_C1  12
+#define MT6620_RDS_BLER_C2  6
+#define MT6620_RDS_BLER_T1  5000
+#define MT6620_RDS_BLER_T2  5000
+
+static fm_bool bRDS_FirstIn = fm_false;
+static fm_u32 gBLER_CHK_INTERVAL = 5000;
+static fm_u16 GOOD_BLK_CNT = 0, BAD_BLK_CNT = 0;
+static fm_u8 BAD_BLK_RATIO = 0;
+
+static struct fm_callback *fm_cb = NULL;
+static struct fm_basic_interface *fm_bi = NULL;
+
+//static fm_bool mt6620_RDS_support(void);
+static fm_s32 mt6620_RDS_enable(void);
+static fm_s32 mt6620_RDS_disable(void);
+static fm_u16 mt6620_RDS_Get_GoodBlock_Counter(void);
+static fm_u16 mt6620_RDS_Get_BadBlock_Counter(void);
+static fm_u8 mt6620_RDS_Get_BadBlock_Ratio(void);
+static fm_u32 mt6620_RDS_Get_BlerCheck_Interval(void);
+static void mt6620_RDS_Init_Data(rds_t *pstRDSData);
+
+#if 0
+static fm_bool mt6620_RDS_support(void)
+{
+    return fm_true;
+}
+#endif
+static fm_s32 mt6620_RDS_enable(void)
+{
+    fm_u16 page;
+
+    WCN_DBG(FM_DBG | RDSC, "rds enable\n");
+    fm_bi->read(FM_MAIN_PGSEL, &page);
+    fm_bi->write(FM_MAIN_PGSEL, 0x0003); //sleect page3
+
+    fm_bi->write(0xCB, 0xE016);
+
+    fm_bi->write(FM_MAIN_PGSEL, 0x0000); //sleect page0
+
+    fm_bi->write(0x63, 0x0491);
+    fm_bi->setbits(0x6B, 0x2000, 0xFFFF);
+
+    fm_bi->write(FM_MAIN_PGSEL, page); //recover page
+    return 0;
+}
+
+static fm_s32 mt6620_RDS_disable(void)
+{
+    WCN_DBG(FM_DBG | RDSC, "rds disable\n");
+    fm_bi->setbits(0x6B, 0x0000, 0xDFFF);
+    fm_bi->write(0x63, 0x0481);
+
+    return 0;
+}
+
+static fm_u16 mt6620_RDS_Get_GoodBlock_Counter(void)
+{
+    fm_u16 tmp_reg;
+    fm_u16 page;
+
+    fm_bi->read(FM_MAIN_PGSEL, &page);
+    fm_bi->write(FM_MAIN_PGSEL, 0x0003);
+
+    fm_bi->read(FM_RDS_GOODBK_CNT, &tmp_reg);
+    GOOD_BLK_CNT = tmp_reg;
+
+    fm_bi->write(FM_MAIN_PGSEL, page);
+    WCN_DBG(FM_DBG | RDSC, "get good block cnt:%d\n", (fm_s32)tmp_reg);
+
+    return tmp_reg;
+}
+
+static fm_u16 mt6620_RDS_Get_BadBlock_Counter(void)
+{
+    fm_u16 tmp_reg;
+    fm_u16 page;
+
+    fm_bi->read(FM_MAIN_PGSEL, &page);
+    fm_bi->write(FM_MAIN_PGSEL, 0x0003);
+
+    fm_bi->read(FM_RDS_BADBK_CNT, &tmp_reg);
+    BAD_BLK_CNT = tmp_reg;
+
+    fm_bi->write(FM_MAIN_PGSEL, page);
+    WCN_DBG(FM_DBG | RDSC, "get bad block cnt:%d\n", (fm_s32)tmp_reg);
+
+    return tmp_reg;
+}
+
+static fm_u8 mt6620_RDS_Get_BadBlock_Ratio(void)
+{
+    fm_u16 tmp_reg;
+    fm_u16 gbc;
+    fm_u16 bbc;
+
+    gbc = mt6620_RDS_Get_GoodBlock_Counter();
+    bbc = mt6620_RDS_Get_BadBlock_Counter();
+
+    if ((gbc + bbc) > 0) {
+        tmp_reg = (fm_u8)(bbc * 100 / (gbc + bbc));
+    } else {
+        tmp_reg = 0;
+    }
+
+    BAD_BLK_RATIO = tmp_reg;
+    WCN_DBG(FM_DBG | RDSC, "get badblock ratio:%d\n", (fm_s32)tmp_reg);
+
+    return tmp_reg;
+}
+
+static fm_s32 mt6620_RDS_BlockCounter_Reset(void)
+{
+    fm_u16 page;
+
+    fm_bi->read(FM_MAIN_PGSEL, &page);
+    fm_bi->write(FM_MAIN_PGSEL, 0x0003);
+
+    fm_bi->write(0xC8, 0x0001);
+    fm_bi->write(0xC8, 0x0002);
+
+    fm_bi->write(FM_MAIN_PGSEL, page);
+
+    return 0;
+}
+
+static fm_u32 mt6620_RDS_Get_BlerCheck_Interval(void)
+{
+    return gBLER_CHK_INTERVAL;
+}
+
+static fm_s32 mt6620_RDS_Reset(void)
+{
+    fm_u16 page;
+
+    fm_bi->read(FM_MAIN_PGSEL, &page);
+    fm_bi->write(FM_MAIN_PGSEL, 0x0003);
+
+    fm_bi->write(0xB0, 0x0001);
+
+    fm_bi->write(FM_MAIN_PGSEL, page);
+
+    return 0;
+}
+
+static fm_s32 mt6620_RDS_Reset_Block(void)
+{
+    fm_u16 page;
+
+    fm_bi->read(FM_MAIN_PGSEL, &page);
+    fm_bi->write(FM_MAIN_PGSEL, 0x0003);
+
+    fm_bi->write(0xDD, 0x0001);
+
+    fm_bi->write(FM_MAIN_PGSEL, page);
+
+    return 0;
+}
+
+static fm_s32 mt6620_RDS_BlerCheck(rds_t *dst)
+{
+    fm_s32 ret = 0;
+    fm_u16 TOTAL_CNT;
+    static fm_u16 RDS_Sync_Cnt;
+    static fm_u16 RDS_Block_Reset_Cnt;
+#if 0
+    if (dst->AF_Data.Addr_Cnt == 0xFF) {
+        //AF List Finished
+        dst->event_status |= RDS_EVENT_AF;  //Need notfiy application
+        //loop dst->event_status then act
+        if (dst->event_status != 0) {
+            //fm->RDS_Data_ready = true;
+            //wake_up_interruptible(&fm->read_wait);
+            //FIXME
+            WCN_DBG(FM_DBG | RDSC, "RDS_EVENT_AF, trigger read\n");
+        }
+    }
+#endif
+    gBLER_CHK_INTERVAL = MT6620_RDS_BLER_T1;
+    GOOD_BLK_CNT = mt6620_RDS_Get_GoodBlock_Counter();
+    BAD_BLK_CNT = mt6620_RDS_Get_BadBlock_Counter();
+    TOTAL_CNT = GOOD_BLK_CNT + BAD_BLK_CNT;
+
+    mt6620_RDS_BlockCounter_Reset();
+
+    if ((GOOD_BLK_CNT == 0) && (BAD_BLK_CNT == 0)) {
+        BAD_BLK_RATIO = 0;
+    } else {
+        BAD_BLK_RATIO = (BAD_BLK_CNT * 100) / TOTAL_CNT;
+    }
+
+    if ((BAD_BLK_RATIO < MT6620_RDS_BLER_TH2) && (RDS_Sync_Cnt > MT6620_RDS_BLER_C1)) {
+        gBLER_CHK_INTERVAL = MT6620_RDS_BLER_T2;
+
+        if (RDS_Block_Reset_Cnt > 1)
+            RDS_Block_Reset_Cnt--;
+    } else {
+        if (BAD_BLK_RATIO > MT6620_RDS_BLER_TH1) {
+            //>90%
+            mt6620_RDS_BlockCounter_Reset();
+            RDS_Sync_Cnt = 0;   //need clear or not, Question, LCH.
+            RDS_Block_Reset_Cnt++;
+
+            if ((RDS_Block_Reset_Cnt > MT6620_RDS_BLER_C2) || bRDS_FirstIn) {
+                if (bRDS_FirstIn)
+                    bRDS_FirstIn = false;
+
+                if ((ret = mt6620_RDS_Reset()))
+                    return ret;
+
+                RDS_Block_Reset_Cnt = 0;
+                WCN_DBG(FM_DBG | RDSC, "RDS Reset, blk_cnt:%d, RDS_FirstIn:%d\n", RDS_Block_Reset_Cnt, bRDS_FirstIn);
+            } else if (TOTAL_CNT > 12) {
+                //LCH question 2, why 12???
+                WCN_DBG(FM_DBG | RDSC, "RDS Block Reset: %x\n", RDS_Block_Reset_Cnt);
+
+                if ((ret = mt6620_RDS_Reset_Block()))
+                    return ret;
+            }
+        } else {
+            RDS_Sync_Cnt++; //(60%-90%)
+            WCN_DBG(FM_DBG | RDSC, "RDS Sync Cnt: %d\n", RDS_Block_Reset_Cnt);
+
+            if (RDS_Block_Reset_Cnt > 1)
+                RDS_Block_Reset_Cnt--;
+
+            if (RDS_Sync_Cnt > MT6620_RDS_BLER_C1) {
+                gBLER_CHK_INTERVAL = MT6620_RDS_BLER_T2;
+            }
+        }
+    }
+
+    return ret;
+}
+
+static void mt6620_RDS_Init_Data(rds_t *pstRDSData)
+{
+    fm_memset(pstRDSData, 0 , sizeof(rds_t));
+    bRDS_FirstIn = fm_true;
+
+    fm_memset(pstRDSData->RT_Data.TextData, 0x20, sizeof(pstRDSData->RT_Data.TextData));
+    fm_memset(pstRDSData->PS_Data.PS, '\0', sizeof(pstRDSData->PS_Data.PS));
+    fm_memset(pstRDSData->PS_ON, 0x20, sizeof(pstRDSData->PS_ON));
+}
+
+fm_bool mt6620_RDS_OnOff(rds_t *dst, fm_bool bFlag)
+{
+#if 0
+    if (mt6620_RDS_support() == fm_false) {
+        WCN_DBG(FM_ALT | RDSC, "mt6620_RDS_OnOff failed, RDS not support\n");
+        return fm_false;
+    }
+#endif
+    if (bFlag) {
+        mt6620_RDS_Init_Data(dst);
+        mt6620_RDS_enable();
+    } else {
+        mt6620_RDS_disable();
+    }
+
+    return fm_true;
+}
+
+DEFINE_RDSLOG(mt6620_rds_log);
+
+/* mt6620_RDS_Efm_s32_Handler    -    response FM RDS interrupt
+ * @fm - main data structure of FM driver
+ * This function first get RDS raw data, then call RDS spec parser
+ */
+static fm_s32 mt6620_rds_parser(rds_t *rds_dst, struct rds_rx_t *rds_raw, fm_s32 rds_size, fm_u16(*getfreq)(void))
+{
+    mt6620_rds_log.log_in(&mt6620_rds_log, rds_raw, rds_size);
+    return rds_parser(rds_dst, rds_raw, rds_size, getfreq);
+}
+
+static fm_s32 mt6620_rds_log_get(struct rds_rx_t *dst, fm_s32 *dst_len)
+{
+    return mt6620_rds_log.log_out(&mt6620_rds_log, dst, dst_len);
+}
+
+static fm_s32 mt6620_rds_gc_get(struct rds_group_cnt_t *dst, rds_t *rdsp)
+{
+    return rds_grp_counter_get(dst, &rdsp->gc);
+}
+
+static fm_s32 mt6620_rds_gc_reset(rds_t *rdsp)
+{
+    return rds_grp_counter_reset(&rdsp->gc);
+}
+
+fm_s32 MT6620fm_rds_ops_register(struct fm_lowlevel_ops *ops)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(ops);
+    FMR_ASSERT(ops->bi.write);
+    FMR_ASSERT(ops->bi.read);
+    FMR_ASSERT(ops->bi.setbits);
+    FMR_ASSERT(ops->bi.usdelay);
+    fm_bi = &ops->bi;
+
+    FMR_ASSERT(ops->cb.cur_freq_get);
+    FMR_ASSERT(ops->cb.cur_freq_set);
+    fm_cb = &ops->cb;
+
+    ops->ri.rds_blercheck = mt6620_RDS_BlerCheck;
+    ops->ri.rds_onoff = mt6620_RDS_OnOff;
+    ops->ri.rds_parser = mt6620_rds_parser;
+    ops->ri.rds_gbc_get = mt6620_RDS_Get_GoodBlock_Counter;
+    ops->ri.rds_bbc_get = mt6620_RDS_Get_BadBlock_Counter;
+    ops->ri.rds_bbr_get = mt6620_RDS_Get_BadBlock_Ratio;
+    ops->ri.rds_bc_reset = mt6620_RDS_BlockCounter_Reset;
+    ops->ri.rds_bci_get = mt6620_RDS_Get_BlerCheck_Interval;
+    ops->ri.rds_log_get = mt6620_rds_log_get;
+    ops->ri.rds_gc_get = mt6620_rds_gc_get;
+    ops->ri.rds_gc_reset = mt6620_rds_gc_reset;
+    return ret;
+}
+
+fm_s32 MT6620fm_rds_ops_unregister(struct fm_lowlevel_ops *ops)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(ops);
+
+    fm_bi = NULL;
+    fm_memset(&ops->ri, 0, sizeof(struct fm_rds_interface));
+    return ret;
+}
+
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6626/inc/mt6626_drv_dsp.h b/drivers/mtk_wcn_combo/drv_fm/mt6626/inc/mt6626_drv_dsp.h
new file mode 100755 (executable)
index 0000000..f333f7e
--- /dev/null
@@ -0,0 +1,10639 @@
+
+const unsigned char channel_parameter[] = {
+0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,1
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,2
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,1
+,1
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,1
+,1
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,2
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,1
+,1
+,1
+,1
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,1
+,0
+,0
+,0
+,0
+,0
+,2
+,0
+,0
+,0
+,0
+,5
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,1
+,1
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,2
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,1
+,1
+,1
+,0
+,0
+,0
+};
+
+#if defined(MT6626_FPGA)
+const unsigned short bin_rom[] = {
+0x0000
+,0x1FFF
+,0xBC00
+,0x0010
+,0xBC00
+,0x0271
+,0x8EC8
+,0x8E00
+,0x8EC8
+,0x8E00
+,0x8EC8
+,0x8E00
+,0x8EC8
+,0x8E00
+,0x8EC8
+,0x8E00
+,0x8EC8
+,0x8E00
+,0xBC02
+,0x0906
+,0xBC20
+,0x2019
+,0x4021
+,0xFB11
+,0xBC02
+,0x0807
+,0xBC20
+,0x2019
+,0x4041
+,0xFB11
+,0xBC22
+,0x0480
+,0xBC20
+,0x0080
+,0x4001
+,0x8B02
+,0xE401
+,0xBC21
+,0x0367
+,0xA301
+,0x0080
+,0xBC20
+,0x201A
+,0x41E1
+,0xFA12
+,0xA302
+,0x0082
+,0x0891
+,0x2620
+,0x8FF9
+,0x3D02
+,0xBC21
+,0x2018
+,0x481E
+,0xBC22
+,0x2019
+,0x8C69
+,0x40C0
+,0xA203
+,0x0082
+,0x2631
+,0x8F4B
+,0x2634
+,0x8F3E
+,0x2632
+,0x8F1D
+,0xB306
+,0x0008
+,0x8F0A
+,0x40E0
+,0xFB50
+,0xBC02
+,0x1E58
+,0xBC22
+,0x2019
+,0xBC21
+,0x2018
+,0x481E
+,0x8C53
+,0x40C0
+,0xFB50
+,0xFA33
+,0x26B0
+,0x8F08
+,0xBC02
+,0x072A
+,0xBC21
+,0x2018
+,0x4020
+,0x7207
+,0xBB30
+,0x40C0
+,0xBC22
+,0x2019
+,0xA31E
+,0x0082
+,0x8D41
+,0x40A0
+,0x70E0
+,0x3B50
+,0xBC21
+,0x201D
+,0xBC22
+,0x201B
+,0xFA31
+,0xFA52
+,0x0810
+,0xBC3E
+,0x00E4
+,0xBC3A
+,0x0692
+,0xB400
+,0x0002
+,0xA31E
+,0x0083
+,0xA31A
+,0x0084
+,0x0408
+,0xBC02
+,0x0131
+,0x40C0
+,0xBC22
+,0x2019
+,0xBC21
+,0x2018
+,0x481E
+,0x8D23
+,0x4080
+,0xFB50
+,0xBC02
+,0x016B
+,0x40C0
+,0xBC22
+,0x2019
+,0xBC21
+,0x2018
+,0x481E
+,0x8D18
+,0x4060
+,0xBC21
+,0x201F
+,0xFB50
+,0xFA30
+,0xBC3E
+,0x00C8
+,0xBC3A
+,0x0652
+,0xBC21
+,0x03FF
+,0xA31E
+,0x0083
+,0xA31A
+,0x0084
+,0x0801
+,0xBC02
+,0x0131
+,0x40C0
+,0xBC22
+,0x2019
+,0xBC21
+,0x2018
+,0x481E
+,0xA203
+,0x0082
+,0xB316
+,0x0040
+,0x8F91
+,0xBC00
+,0x001C
+,0x6915
+,0xA902
+,0x8E00
+,0xA30E
+,0x0085
+,0xDFD5
+,0xBC02
+,0x0607
+,0xBC02
+,0x077A
+,0xBC20
+,0x2019
+,0x7040
+,0x4FD5
+,0xBC22
+,0x2008
+,0xFB11
+,0xFA51
+,0xBC23
+,0x4000
+,0x0ACB
+,0xBC21
+,0x2100
+,0xFB53
+,0xFA32
+,0xB314
+,0x0020
+,0x8FFB
+,0x4121
+,0xE9FE
+,0xFB11
+,0xBC00
+,0x1D52
+,0xE902
+,0xBC20
+,0x2019
+,0x7060
+,0x5FD5
+,0x8C02
+,0xFB11
+,0x8E00
+,0xA200
+,0x008B
+,0x2600
+,0x8FFA
+,0x3E02
+,0xA200
+,0x008C
+,0x6980
+,0x4FD5
+,0x8F02
+,0xA200
+,0x0086
+,0x2681
+,0x8F02
+,0x4080
+,0xA300
+,0x0082
+,0x8EC0
+,0xE9FE
+,0x8E00
+,0xE902
+,0xBC20
+,0x2019
+,0x7068
+,0x5FD5
+,0x8C02
+,0xFB11
+,0x8E00
+,0xA200
+,0x008B
+,0x2600
+,0x8FFA
+,0x3E02
+,0xA200
+,0x008C
+,0xA201
+,0x0088
+,0x2681
+,0x8F06
+,0x4020
+,0xA202
+,0x008A
+,0x1401
+,0x0A10
+,0xA300
+,0x008A
+,0x3409
+,0xA300
+,0x0088
+,0xA201
+,0x0086
+,0xB300
+,0x0010
+,0x8F01
+,0x2691
+,0x8F09
+,0x401C
+,0xBC20
+,0x2041
+,0xA202
+,0x008A
+,0xA31C
+,0x0088
+,0xA31C
+,0x008A
+,0xFB12
+,0x2691
+,0x8F16
+,0xBC20
+,0x2019
+,0x41C1
+,0x7008
+,0x7B11
+,0xBC22
+,0x2018
+,0xBC20
+,0x201A
+,0x8C05
+,0xFB51
+,0x8E00
+,0xBC20
+,0x201A
+,0x8E00
+,0xFA10
+,0xB310
+,0x0008
+,0x8FF6
+,0x7040
+,0x0FD5
+,0x8C03
+,0xA300
+,0x0082
+,0xCFD5
+,0x8E00
+,0x8EC0
+,0xE9FE
+,0x8E00
+,0xE902
+,0x8E00
+,0xDFC0
+,0xDFF5
+,0xBC02
+,0x05A2
+,0xA200
+,0x0087
+,0x2680
+,0x8F0C
+,0xBC20
+,0x2040
+,0x7000
+,0x4FC3
+,0x700F
+,0xBB11
+,0x4042
+,0xA303
+,0x0089
+,0xA31E
+,0x0087
+,0xA301
+,0x0086
+,0xFB12
+,0xA200
+,0x0084
+,0x8EA0
+,0xBC20
+,0x02C7
+,0xA300
+,0x009B
+,0xBC02
+,0x00A7
+,0x3E01
+,0xBC20
+,0x2008
+,0xBC21
+,0x033D
+,0xA202
+,0x0083
+,0xFB11
+,0x8EA2
+,0xBC20
+,0x2008
+,0x7000
+,0x4FF5
+,0xBC22
+,0x201A
+,0x7040
+,0x3B11
+,0xFA51
+,0x2248
+,0x8F00
+,0xA300
+,0x0082
+,0x8EC0
+,0xE9FE
+,0x8E00
+,0xE902
+,0x8E00
+,0xDFD5
+,0xBC02
+,0x0480
+,0xBC20
+,0x02B3
+,0xA300
+,0x009B
+,0xBC02
+,0x00A7
+,0x3E01
+,0xBC20
+,0x2008
+,0xBC21
+,0x03F7
+,0xBC22
+,0x2018
+,0x7008
+,0x3B11
+,0x7050
+,0x3B50
+,0xBC21
+,0x2019
+,0x8C2E
+,0xFB30
+,0xA200
+,0x0081
+,0x2601
+,0x8F04
+,0xBC21
+,0x8000
+,0xBC20
+,0x2023
+,0x8C24
+,0xFB11
+,0xBC02
+,0x01BE
+,0xA200
+,0x0085
+,0x4001
+,0xA301
+,0x0081
+,0x2682
+,0x8F02
+,0x4100
+,0xA300
+,0x0082
+,0xBC02
+,0x1E58
+,0xBC20
+,0x201A
+,0x8E00
+,0xFA10
+,0xB310
+,0x0008
+,0x8F05
+,0xBC20
+,0x2019
+,0x4161
+,0x7008
+,0x3B11
+,0xA300
+,0x0085
+,0xBC02
+,0x077A
+,0xBC20
+,0x2023
+,0xBC21
+,0x8000
+,0xFB11
+,0xA200
+,0x0082
+,0x2604
+,0x8FCE
+,0x3E02
+,0x7000
+,0x4FD5
+,0xBC20
+,0x2008
+,0x8EC0
+,0xE9FE
+,0xFB11
+,0xE902
+,0xA200
+,0x0098
+,0x6CE0
+,0x1FD5
+,0x8F57
+,0xBC02
+,0x0918
+,0xBC20
+,0x01AE
+,0xBC02
+,0x09F0
+,0xA200
+,0x02A7
+,0x2682
+,0x8F02
+,0xBC20
+,0x01AE
+,0xBC02
+,0x0D50
+,0xA200
+,0x008E
+,0x2606
+,0x8F1E
+,0x2604
+,0x8F17
+,0x2602
+,0x8F0B
+,0x2600
+,0x8F05
+,0xA200
+,0x008D
+,0x2680
+,0x8F20
+,0xBC02
+,0x0BDE
+,0x8D1F
+,0xBC02
+,0x0E6E
+,0x8D1C
+,0xBC20
+,0x2032
+,0x4101
+,0xFA10
+,0x0801
+,0xA300
+,0x01E3
+,0xBC02
+,0x0A17
+,0x8D12
+,0xBC02
+,0x0AA2
+,0xBC02
+,0x0CA4
+,0x8D0D
+,0xA200
+,0x0085
+,0x2601
+,0x8F05
+,0xA200
+,0x02C7
+,0x2601
+,0x8F01
+,0xBC02
+,0x0B48
+,0x8D02
+,0xBC02
+,0x0B2B
+,0xA201
+,0x01BE
+,0xBC20
+,0x01AE
+,0xBC02
+,0x0A72
+,0xBC20
+,0x01E7
+,0xBC02
+,0x0B04
+,0xA200
+,0x0266
+,0x2680
+,0xBC20
+,0x01E7
+,0x8F03
+,0xBC21
+,0x7FFF
+,0xBC02
+,0x0B8C
+,0x8D04
+,0xA201
+,0x01FF
+,0xBC02
+,0x0B8C
+,0xBC02
+,0x0C54
+,0xA200
+,0x0099
+,0x2600
+,0x8F02
+,0xBC02
+,0x195E
+,0xBC02
+,0x1926
+,0xA200
+,0x009A
+,0x2600
+,0x8F02
+,0xB000
+,0xFFFF
+,0xA300
+,0x009A
+,0xBC20
+,0x2040
+,0x4021
+,0xFA10
+,0x0801
+,0x2600
+,0x8F0A
+,0xBC20
+,0x2023
+,0xBC21
+,0x4000
+,0xFA10
+,0x0801
+,0x2680
+,0x8F02
+,0xA200
+,0x009A
+,0x2600
+,0x8F15
+,0x3E02
+,0x4000
+,0xA300
+,0x0099
+,0x3E01
+,0xBC20
+,0x2008
+,0xBC21
+,0x0080
+,0xFA12
+,0x0851
+,0x2610
+,0x8F0B
+,0xFA11
+,0xBC22
+,0xFF7F
+,0x084A
+,0x7000
+,0x3B11
+,0xBC02
+,0x05B3
+,0x8D03
+,0x4020
+,0xA300
+,0x0099
+,0x7038
+,0x4FD5
+,0xA200
+,0x008E
+,0xE9FE
+,0x3401
+,0x8EC0
+,0x0801
+,0xA300
+,0x008E
+,0x4020
+,0xBC21
+,0x00C0
+,0xA300
+,0x0091
+,0xA300
+,0x0092
+,0xA301
+,0x0098
+,0x8EC0
+,0xA300
+,0x0090
+,0xA300
+,0x008F
+,0xE918
+,0x8E00
+,0xDD05
+,0xBC25
+,0x2096
+,0xDD5B
+,0xFAB5
+,0xA205
+,0x009B
+,0xDD7A
+,0xDD9F
+,0xDDBE
+,0xDDDD
+,0xDDFC
+,0xDE0B
+,0xDE2C
+,0xDE49
+,0xDE68
+,0xDE8F
+,0xDEAE
+,0xDED5
+,0xDEE6
+,0xDF04
+,0xDF23
+,0xDF42
+,0xDF61
+,0xDF80
+,0xDD27
+,0xF9FC
+,0x8EA5
+,0xBC20
+,0x2096
+,0xBC21
+,0x00FF
+,0xFA10
+,0x6220
+,0x4D05
+,0xA203
+,0x0096
+,0x6854
+,0xCD27
+,0x6624
+,0xCF80
+,0xA302
+,0x0096
+,0xCF61
+,0xCF42
+,0xCF23
+,0xCF04
+,0xCEE6
+,0xCDFC
+,0xCDDD
+,0xCDBE
+,0xCD9F
+,0xCD7A
+,0xCD5B
+,0xF8FC
+,0xCED5
+,0xCEAE
+,0xCE8F
+,0xCE68
+,0xCE49
+,0xCE2C
+,0xCE0B
+,0xE9E8
+,0x8EC8
+,0xBC20
+,0x2102
+,0xBC21
+,0x8000
+,0xFA10
+,0x0801
+,0x6980
+,0x2902
+,0x8F07
+,0xDFD5
+,0xBC02
+,0x02DB
+,0xBC20
+,0x02DB
+,0xCFD5
+,0xA300
+,0x009B
+,0x8EC0
+,0xE9FE
+,0x8E00
+,0xBC20
+,0x2104
+,0xBC21
+,0x8000
+,0xFA10
+,0x0801
+,0x6980
+,0x2902
+,0x8F07
+,0xDFD5
+,0xBC02
+,0x0423
+,0xBC20
+,0x0423
+,0xCFD5
+,0xA300
+,0x009B
+,0x8EC0
+,0xE9FE
+,0x8E00
+,0xE906
+,0xA202
+,0x0090
+,0x69A8
+,0x1F95
+,0x8F19
+,0xBC24
+,0x2081
+,0xBC23
+,0x2082
+,0xFA95
+,0xBC24
+,0x2015
+,0xFA73
+,0xA21A
+,0x0461
+,0xA21E
+,0x046B
+,0xA210
+,0x0361
+,0xFA94
+,0xA305
+,0x02CA
+,0xA303
+,0x02CB
+,0xA310
+,0x02C8
+,0xA31A
+,0x02C9
+,0xA304
+,0x02CC
+,0xA31E
+,0x02CD
+,0x26A6
+,0x8F32
+,0xBC23
+,0x027F
+,0xBC24
+,0x026F
+,0x4022
+,0xBD10
+,0x0306
+,0xE205
+,0xE585
+,0xA21C
+,0x02C8
+,0xA21A
+,0x02CA
+,0xA21E
+,0x02CB
+,0xA210
+,0x02C9
+,0xA205
+,0x02CC
+,0xA203
+,0x02CD
+,0xA204
+,0x0081
+,0xA31C
+,0x02C2
+,0xA310
+,0x02C3
+,0xA31A
+,0x02C4
+,0xA31E
+,0x02C5
+,0xA305
+,0x02C6
+,0xA303
+,0x02C7
+,0x2640
+,0x8F03
+,0xA203
+,0x0095
+,0x34D9
+,0xA303
+,0x0095
+,0xA203
+,0x0098
+,0xA302
+,0x0081
+,0x3230
+,0x8F02
+,0xB026
+,0xFFFF
+,0xA302
+,0x0098
+,0xA200
+,0x028F
+,0x421E
+,0x403A
+,0xBC3C
+,0x027F
+,0xBC22
+,0x2033
+,0xE064
+,0xBC23
+,0x2034
+,0xE065
+,0xFB54
+,0xFB75
+,0xA300
+,0x028F
+,0xBC02
+,0x1BC3
+,0xBC22
+,0x3105
+,0xA200
+,0x0313
+,0x700E
+,0xBA52
+,0x3BC2
+,0xBC22
+,0x2139
+,0xBC3C
+,0x02E0
+,0xBD05
+,0x0352
+,0xFA53
+,0xE463
+,0xA202
+,0x0099
+,0x2620
+,0xA300
+,0x0313
+,0x385A
+,0x8F10
+,0xBC23
+,0x2008
+,0xBC24
+,0x0080
+,0xFA75
+,0x0B2C
+,0xBC25
+,0x2103
+,0xFB74
+,0xFAB3
+,0xBC24
+,0x4000
+,0x08DC
+,0x2630
+,0x8F01
+,0xBC02
+,0x15BE
+,0x4022
+,0xA203
+,0x0091
+,0x26B0
+,0x8F05
+,0xBC20
+,0x2012
+,0xBC21
+,0x2014
+,0xBC02
+,0x106C
+,0x4022
+,0xA203
+,0x0093
+,0xB306
+,0x0011
+,0x4003
+,0x1893
+,0xA204
+,0x0091
+,0x6D28
+,0x5FA2
+,0x4244
+,0x2214
+,0x18DA
+,0xA202
+,0x008F
+,0x2620
+,0xA303
+,0x0091
+,0x8F67
+,0x2621
+,0x8F53
+,0x2622
+,0x8F2B
+,0x26A3
+,0x8F26
+,0xBC02
+,0x118C
+,0xCFA2
+,0x2620
+,0xBC20
+,0x2015
+,0x8F0E
+,0xA201
+,0x0097
+,0xBC02
+,0x101D
+,0xBC02
+,0x1391
+,0xBC02
+,0x1DAA
+,0xA202
+,0x0097
+,0x2622
+,0x4043
+,0x8F00
+,0x34D1
+,0xA303
+,0x0097
+,0xA202
+,0x0093
+,0x3511
+,0x4242
+,0x21E2
+,0xA203
+,0x0094
+,0x4005
+,0x34D9
+,0x192C
+,0x4062
+,0x08DA
+,0xA304
+,0x0093
+,0x8C51
+,0xA303
+,0x0094
+,0x8C4E
+,0x4062
+,0x3854
+,0xB004
+,0xFFFB
+,0xDFC0
+,0xBC02
+,0x121B
+,0x6E15
+,0x0FC0
+,0xB014
+,0xFFFA
+,0xDFC1
+,0xBC02
+,0x1277
+,0xBC02
+,0x12BC
+,0xCFC0
+,0xBC21
+,0x0464
+,0xBC02
+,0x1326
+,0x7018
+,0x8FA3
+,0x2630
+,0x8F33
+,0xA201
+,0x0097
+,0xBC20
+,0x2013
+,0xBC02
+,0x1037
+,0xA201
+,0x0097
+,0xBC20
+,0x200B
+,0xBC02
+,0x1092
+,0x4062
+,0x8D27
+,0xBC02
+,0x118C
+,0xBC02
+,0x11E4
+,0xBC02
+,0x1B03
+,0x7018
+,0x8FA3
+,0x2630
+,0x8F1B
+,0xA201
+,0x0097
+,0xBC20
+,0x2011
+,0xBC02
+,0x10B6
+,0x4062
+,0x8D15
+,0xBC02
+,0x12BC
+,0xCFA2
+,0x2620
+,0x8F00
+,0xBC02
+,0x1E00
+,0xBC02
+,0x10FF
+,0xA202
+,0x0094
+,0x26A0
+,0x4062
+,0x8F05
+,0xA203
+,0x047B
+,0x2630
+,0x8F01
+,0xBC02
+,0x115E
+,0x4062
+,0xA204
+,0x008F
+,0xA203
+,0x0090
+,0x6D48
+,0x4F95
+,0x34D9
+,0x40E6
+,0xA205
+,0x008D
+,0x08DE
+,0x08A2
+,0x26D0
+,0xA303
+,0x0090
+,0xA302
+,0x008F
+,0x8F04
+,0xBC22
+,0x31F8
+,0xDF95
+,0xFA52
+,0x8EA2
+,0xCF95
+,0x8E00
+,0x8EC0
+,0xE9FA
+,0x8E00
+,0xE902
+,0xA200
+,0x0092
+,0xDFC0
+,0xDFF5
+,0xBC02
+,0x10DC
+,0xCFC0
+,0xB300
+,0x0044
+,0x8F2B
+,0xA201
+,0x0097
+,0xB300
+,0x0045
+,0x8F21
+,0xB300
+,0x0046
+,0x8F14
+,0xCFC0
+,0xB310
+,0x0047
+,0x8F21
+,0xA200
+,0x0470
+,0x2680
+,0x8F00
+,0xBC02
+,0x0F91
+,0xBC02
+,0x1DAA
+,0xA200
+,0x0097
+,0x2602
+,0x4041
+,0x8F00
+,0x3441
+,0xA301
+,0x0097
+,0x8D12
+,0xBC20
+,0x2013
+,0xBC02
+,0x1037
+,0xA201
+,0x0097
+,0xBC20
+,0x200B
+,0xBC02
+,0x1092
+,0x8D07
+,0xBC20
+,0x2011
+,0xBC02
+,0x10B6
+,0x8D02
+,0xBC02
+,0x1E00
+,0x7240
+,0x4FC0
+,0x6D00
+,0x4FF5
+,0x21C1
+,0x4001
+,0x1808
+,0xA201
+,0x008D
+,0x2690
+,0xA300
+,0x0092
+,0x8F04
+,0xBC20
+,0x31F8
+,0xDFD5
+,0xFA10
+,0x8EA0
+,0xCFD5
+,0x8E00
+,0x8EC0
+,0xE9FE
+,0x8E00
+,0xBC20
+,0x009C
+,0xBC21
+,0x047C
+,0x0448
+,0x3489
+,0x32A0
+,0x4001
+,0x8F01
+,0x8B02
+,0xE401
+,0x8EB8
+,0xE902
+,0x8E00
+,0xDFD5
+,0xBC02
+,0x0474
+,0xBC20
+,0x3173
+,0xBC21
+,0x3010
+,0xBC24
+,0x02A8
+,0xBC22
+,0x2032
+,0x7014
+,0x3A10
+,0x4085
+,0x700F
+,0x3A31
+,0xA300
+,0x01E5
+,0xFA53
+,0xBC40
+,0x1605
+,0xA301
+,0x0467
+,0x4100
+,0xBC40
+,0x1E10
+,0xBC40
+,0x2610
+,0x6206
+,0x2610
+,0xFA51
+,0x6213
+,0x6650
+,0xBC3A
+,0x0184
+,0xBC3E
+,0x01C0
+,0x4503
+,0x4444
+,0xBC2E
+,0x0160
+,0xBC2F
+,0x0170
+,0xB048
+,0x009C
+,0xB056
+,0x009C
+,0xA300
+,0x01E3
+,0xA301
+,0x01F7
+,0xA31C
+,0x0468
+,0xA31C
+,0x0461
+,0xA31C
+,0x045C
+,0xA30E
+,0x016E
+,0xA30F
+,0x017E
+,0xA31A
+,0x01AC
+,0xA31A
+,0x01AD
+,0xA31E
+,0x01E0
+,0xA31E
+,0x01E1
+,0xA304
+,0x015E
+,0xA305
+,0x015F
+,0xBC20
+,0x3136
+,0xBC21
+,0x3163
+,0xBD04
+,0x04D2
+,0xFA04
+,0xFB24
+,0xFA0C
+,0xFB24
+,0xBD04
+,0x04D8
+,0xFA0C
+,0xFB24
+,0xBC20
+,0x31B2
+,0x7717
+,0xBA51
+,0x7006
+,0xBA14
+,0x38BC
+,0x084D
+,0xB048
+,0x319C
+,0xA301
+,0x0266
+,0xBC20
+,0x0200
+,0xFA91
+,0xB040
+,0x0050
+,0xB060
+,0x0010
+,0xA304
+,0x0261
+,0xA300
+,0x0260
+,0xA306
+,0x0262
+,0xFA52
+,0x4044
+,0x1609
+,0x41E6
+,0x0894
+,0x1406
+,0xB4F2
+,0x0001
+,0x0B07
+,0xBC20
+,0x01F9
+,0xA302
+,0x02A7
+,0xBC40
+,0x1C01
+,0xBC40
+,0x3401
+,0x144E
+,0x24A1
+,0xBC24
+,0x029A
+,0xBC40
+,0x140C
+,0xBC21
+,0x0267
+,0xBC22
+,0x0294
+,0xBC3C
+,0x4000
+,0x6D79
+,0x640E
+,0xBC3F
+,0x0285
+,0xBC3B
+,0x0290
+,0xBC30
+,0x2000
+,0x7000
+,0x244F
+,0xBC40
+,0x6607
+,0xA31F
+,0x028F
+,0xA31B
+,0x0293
+,0xBC40
+,0x0C9C
+,0xBC40
+,0x149C
+,0xBC40
+,0x151E
+,0xBC40
+,0x2C80
+,0xBC40
+,0x3490
+,0xBC40
+,0x3C9A
+,0xBC40
+,0x2D10
+,0xBC40
+,0x1D03
+,0x40A7
+,0xBC02
+,0x05B3
+,0xB04A
+,0x0318
+,0xBC23
+,0x30FD
+,0xBC22
+,0x30FF
+,0xA304
+,0x0325
+,0xFA74
+,0xFA52
+,0x04F2
+,0xBC21
+,0x02E0
+,0x3589
+,0xB00E
+,0x0318
+,0xA306
+,0x0312
+,0xA300
+,0x0326
+,0xBC26
+,0x30FC
+,0xBC20
+,0x3102
+,0xFAD6
+,0xFA10
+,0xA306
+,0x0360
+,0x14AA
+,0x1428
+,0x14EB
+,0xA304
+,0x035F
+,0xBC26
+,0x2021
+,0x35CD
+,0xBC25
+,0x0327
+,0xBC24
+,0x07C0
+,0xBC3E
+,0x7FFF
+,0xBC3A
+,0x0320
+,0xB012
+,0x0019
+,0xB024
+,0xFFFF
+,0xB000
+,0xFFFF
+,0x6D4B
+,0x3BD4
+,0xA305
+,0x0354
+,0xA31E
+,0x047A
+,0xA31A
+,0x02DC
+,0xA301
+,0x0314
+,0xA307
+,0x0313
+,0xA304
+,0x0353
+,0xA302
+,0x0363
+,0xA303
+,0x0364
+,0xA300
+,0x0365
+,0xBC02
+,0x0263
+,0xBC02
+,0x07A4
+,0xBC20
+,0x2023
+,0xBC21
+,0x4000
+,0x700F
+,0xBA10
+,0x0801
+,0x2680
+,0x8F09
+,0xBC20
+,0x2040
+,0x7008
+,0x4FD5
+,0xFA10
+,0x0801
+,0x2600
+,0x8F10
+,0xA301
+,0x0099
+,0x8D0F
+,0xBC20
+,0x2008
+,0xBC21
+,0xFF7F
+,0x7007
+,0x3A12
+,0x6214
+,0x4FD5
+,0xA31C
+,0x0099
+,0xA31C
+,0x02A7
+,0xA31E
+,0x008D
+,0xFB11
+,0x8EC0
+,0xE9FE
+,0x8E00
+,0xE902
+,0x8E00
+,0xDFD5
+,0xBC02
+,0x0474
+,0x6914
+,0x4FD5
+,0x4020
+,0xE9FE
+,0xA309
+,0x008B
+,0xA309
+,0x008C
+,0xA300
+,0x00A0
+,0xBC00
+,0x0263
+,0xBC22
+,0x036A
+,0xBC21
+,0x044C
+,0x044A
+,0x3509
+,0x32C0
+,0x4001
+,0x4023
+,0x8F01
+,0x8B04
+,0xE501
+,0x2680
+,0x8F02
+,0xBC22
+,0x2040
+,0x8E00
+,0xFB51
+,0xBC22
+,0x305A
+,0x40BC
+,0x703F
+,0xBA52
+,0xBC3A
+,0x0376
+,0xBC2E
+,0x0399
+,0x4FEF
+,0xBC28
+,0x03A8
+,0x2680
+,0x149A
+,0x4270
+,0xA31E
+,0x0372
+,0xA31A
+,0x0375
+,0xA310
+,0x0395
+,0xA31C
+,0x0396
+,0xA31C
+,0x0397
+,0xA30E
+,0x0398
+,0xA30F
+,0x03B8
+,0xA308
+,0x03A6
+,0xA302
+,0x03A5
+,0xBC20
+,0x2040
+,0x8F01
+,0x4042
+,0xFB12
+,0xBC20
+,0x3079
+,0xBC3E
+,0x03DC
+,0xBC3A
+,0x041A
+,0xBC24
+,0x2044
+,0xFA03
+,0xBC30
+,0x03F1
+,0xA31E
+,0x03DB
+,0xA31A
+,0x0442
+,0xA310
+,0x03F0
+,0xFB91
+,0xA301
+,0x03E2
+,0xA303
+,0x03E0
+,0xBC22
+,0x2043
+,0x8EC0
+,0xA300
+,0x03E1
+,0xFB51
+,0xE902
+,0xA200
+,0x008C
+,0xA201
+,0x0082
+,0x6980
+,0x5FD5
+,0x8F16
+,0x2611
+,0x8F14
+,0x2612
+,0x8F11
+,0xBC20
+,0x201A
+,0x4201
+,0xFA10
+,0x0801
+,0x2680
+,0x8F00
+,0xBC02
+,0x06A8
+,0xBC20
+,0x201F
+,0xBC21
+,0x03FF
+,0xFA10
+,0x0801
+,0xBC22
+,0x2002
+,0x8C06
+,0xFB50
+,0xBC20
+,0x2002
+,0xA201
+,0x0089
+,0xFB11
+,0xBC20
+,0x2000
+,0x4021
+,0xFB11
+,0xFA11
+,0x2693
+,0x8FFC
+,0x8E00
+,0xBC20
+,0x2000
+,0x4001
+,0xBC22
+,0x2020
+,0x7010
+,0x3B11
+,0xFA51
+,0x0808
+,0x2600
+,0x4021
+,0x8F0C
+,0xBC20
+,0x2001
+,0x8E00
+,0xFB11
+,0xFA11
+,0x2693
+,0x8FFC
+,0x8E00
+,0x7000
+,0x4FD5
+,0xBC20
+,0x2001
+,0x8C02
+,0xFB11
+,0xCFD5
+,0x8E00
+,0x8EC0
+,0xE9FE
+,0x8E00
+,0xBC20
+,0x201B
+,0x4022
+,0xFA10
+,0x4381
+,0x0902
+,0x0841
+,0x4043
+,0x2640
+,0x0803
+,0x124B
+,0xA204
+,0x0089
+,0xBC23
+,0x201D
+,0x8F10
+,0x0461
+,0xFA73
+,0xA301
+,0x0089
+,0x218B
+,0x8F1A
+,0x2600
+,0xBC20
+,0x201C
+,0x8F03
+,0xFA10
+,0x8C15
+,0xA300
+,0x0089
+,0xA302
+,0x0086
+,0x8D10
+,0xBC25
+,0x201C
+,0x0061
+,0xFAB4
+,0xA301
+,0x0089
+,0x208C
+,0x8F07
+,0x2600
+,0x8F03
+,0xFA70
+,0x8C04
+,0xA300
+,0x0089
+,0xA302
+,0x0086
+,0xBC20
+,0x201F
+,0xBC21
+,0x03FF
+,0xFA10
+,0xA203
+,0x0089
+,0x0801
+,0x2258
+,0x8F03
+,0x8EC0
+,0xA302
+,0x0086
+,0x8E00
+,0x8EB8
+,0xBC20
+,0x201B
+,0x4381
+,0xFA10
+,0x0801
+,0xA201
+,0x0089
+,0xB480
+,0x0002
+,0xBC22
+,0x201C
+,0x0008
+,0xFA51
+,0x2001
+,0xA300
+,0x0089
+,0x8F03
+,0x8EC0
+,0x4020
+,0xA300
+,0x0086
+,0x8EB8
+,0xE902
+,0xBC22
+,0x2000
+,0xDFD5
+,0x41A3
+,0xBC02
+,0x0723
+,0x4344
+,0xBC25
+,0x0400
+,0x2620
+,0x8F05
+,0xBC02
+,0x07F0
+,0x5404
+,0x4025
+,0xBC02
+,0x07F0
+,0x8D06
+,0xBC02
+,0x07FB
+,0x5404
+,0x4025
+,0xBC02
+,0x07FB
+,0xBC02
+,0x072A
+,0x4E20
+,0xBC02
+,0x07B8
+,0xBC20
+,0x0001
+,0x0848
+,0xB412
+,0x0000
+,0xBC22
+,0x1000
+,0x4183
+,0xBC02
+,0x0723
+,0x220A
+,0x8F3F
+,0xDFE2
+,0xBC21
+,0x2098
+,0x41C2
+,0xFA33
+,0x0ADA
+,0xFB33
+,0x4060
+,0x4841
+,0xBC02
+,0x07D8
+,0xBC21
+,0x2098
+,0x4202
+,0xBC20
+,0xFFFE
+,0x0ADA
+,0xFB33
+,0x08D8
+,0xFB33
+,0x4E20
+,0xBC02
+,0x07B8
+,0xBC22
+,0xFFFE
+,0x084A
+,0xCFE2
+,0x0A4A
+,0xBC02
+,0x07CA
+,0x4224
+,0xBC25
+,0x4000
+,0xBC02
+,0x07FB
+,0x4044
+,0x4045
+,0xBC02
+,0x07FB
+,0x4284
+,0x4105
+,0xBC02
+,0x07FB
+,0x4284
+,0x4105
+,0xBC02
+,0x07F0
+,0xCFE0
+,0xBC02
+,0x0733
+,0x4E24
+,0x4045
+,0xBC02
+,0x07FB
+,0x4E24
+,0x4045
+,0xBC02
+,0x07F0
+,0xBC20
+,0x2098
+,0x43E1
+,0xFB11
+,0x4021
+,0xFB11
+,0xBC22
+,0x4000
+,0x41C3
+,0xBC02
+,0x0723
+,0x38A2
+,0x4E20
+,0xBC02
+,0x07B8
+,0xB55A
+,0x0002
+,0x0A4D
+,0xBC02
+,0x07CA
+,0xCFD5
+,0xE9FE
+,0x8EB8
+,0xBC20
+,0x201F
+,0x8E00
+,0xFA10
+,0x0890
+,0x1093
+,0x8EB8
+,0xE902
+,0x4E24
+,0xDFD5
+,0x4085
+,0xBC02
+,0x07FB
+,0xCFD5
+,0xE9FE
+,0x8EB8
+,0xE902
+,0xBC21
+,0x202D
+,0xDFD5
+,0xDFE0
+,0x4280
+,0xBC02
+,0x07CA
+,0xBC22
+,0x8018
+,0xBC23
+,0x8098
+,0xCFE0
+,0x2600
+,0x1853
+,0x42C0
+,0xBC02
+,0x07CA
+,0x4240
+,0xBC21
+,0xE419
+,0xBC02
+,0x07CA
+,0x4260
+,0xBC21
+,0x9010
+,0xBC02
+,0x07CA
+,0x4040
+,0xBC21
+,0x0FFB
+,0xBC02
+,0x07CA
+,0x4220
+,0xBC21
+,0x2020
+,0xBC02
+,0x07CA
+,0xBC20
+,0x0005
+,0x4461
+,0xBC02
+,0x07D8
+,0x4220
+,0xBC21
+,0x1020
+,0xBC02
+,0x07CA
+,0xBC20
+,0x0005
+,0x4461
+,0xBC02
+,0x07D8
+,0x4220
+,0xBC21
+,0x4020
+,0xBC02
+,0x07CA
+,0xBC20
+,0x0064
+,0x4461
+,0xBC02
+,0x07D8
+,0x4520
+,0xBC21
+,0x8001
+,0xBC02
+,0x07CA
+,0xCFD5
+,0xE9FE
+,0x8EB8
+,0xE902
+,0xBC20
+,0x2023
+,0xDFD5
+,0xFA16
+,0xBC20
+,0x2000
+,0x09B0
+,0xDFE6
+,0x4060
+,0xBC02
+,0x07B8
+,0xBC22
+,0x39AE
+,0xBC23
+,0x19AE
+,0xCFE6
+,0x2660
+,0x195A
+,0x220D
+,0x8F02
+,0x3825
+,0xBC02
+,0x07CA
+,0x4480
+,0xBC02
+,0x07B8
+,0xBC22
+,0x0000
+,0xBC23
+,0x0001
+,0xCFE6
+,0x2660
+,0x195A
+,0x220D
+,0x8F02
+,0x3825
+,0xBC02
+,0x07CA
+,0xCFD5
+,0xE9FE
+,0x8EB8
+,0xE902
+,0x4E04
+,0x4805
+,0xDFD5
+,0xBC20
+,0x2023
+,0xBC21
+,0x4000
+,0xFA10
+,0x0801
+,0x2600
+,0x8F01
+,0xBC02
+,0x07FB
+,0x8D02
+,0xBC02
+,0x07F0
+,0xCFD5
+,0xE9FE
+,0x8EB8
+,0xBC22
+,0x209A
+,0xBC23
+,0x0100
+,0x0AD8
+,0xBC21
+,0x209D
+,0xFB53
+,0x4043
+,0xFA32
+,0x0893
+,0x26A0
+,0x8FFA
+,0xBC22
+,0x209C
+,0x8E00
+,0xFA51
+,0x8EB8
+,0xBC22
+,0x209A
+,0xBC23
+,0x209B
+,0xFB50
+,0xBC22
+,0x209D
+,0xFB71
+,0x4023
+,0xFA51
+,0x084B
+,0x2690
+,0x8FFB
+,0x8EB8
+,0xBC08
+,0x07E6
+,0x8E00
+,0xBDC8
+,0x07E5
+,0x8E00
+,0xBC09
+,0x07E4
+,0x8E00
+,0x8E00
+,0x8E00
+,0x8E00
+,0x8E00
+,0x8E00
+,0x8E00
+,0x8EB8
+,0xBC08
+,0x07EE
+,0x8E00
+,0xBC09
+,0x07ED
+,0x8E00
+,0x8E00
+,0x8EB8
+,0xE902
+,0x3804
+,0xDFD5
+,0xBC02
+,0x07B8
+,0x0A4D
+,0xBC02
+,0x07CA
+,0xCFD5
+,0xE9FE
+,0x8EB8
+,0xE902
+,0x1745
+,0xDFD5
+,0x3804
+,0xBC02
+,0x07B8
+,0x084D
+,0xBC02
+,0x07CA
+,0xCFD5
+,0xE9FE
+,0x8EB8
+,0xBC20
+,0x201A
+,0x4201
+,0xFA10
+,0x0801
+,0x2600
+,0x8F00
+,0x8EB8
+,0xE902
+,0x4020
+,0xDFD5
+,0xBC21
+,0x1F2A
+,0xBC02
+,0x07CA
+,0xBC20
+,0x01F4
+,0x4461
+,0xBC02
+,0x07E8
+,0x4000
+,0xBC21
+,0x402D
+,0xBC02
+,0x07CA
+,0x4280
+,0x4461
+,0xBC02
+,0x07E8
+,0x4000
+,0xBC21
+,0x5FED
+,0xBC02
+,0x07CA
+,0x4020
+,0xBC21
+,0x1F6A
+,0xBC02
+,0x07CA
+,0x4280
+,0x4461
+,0xBC02
+,0x07E8
+,0x4000
+,0xBC21
+,0x7FED
+,0xBC02
+,0x07CA
+,0x4500
+,0x4461
+,0xBC02
+,0x07E8
+,0xBC20
+,0x2023
+,0xBC22
+,0x39AE
+,0xBC23
+,0x19AE
+,0xFA10
+,0xBC21
+,0x2000
+,0x0841
+,0x38C1
+,0x2610
+,0x185A
+,0x4060
+,0xBC02
+,0x07CA
+,0x4040
+,0xBC21
+,0x0FF9
+,0xBC02
+,0x07CA
+,0xBC20
+,0x000A
+,0x4461
+,0xBC02
+,0x07E8
+,0x4022
+,0x4003
+,0x2660
+,0x1853
+,0x4480
+,0xBC02
+,0x07CA
+,0x4540
+,0xBC02
+,0x07B8
+,0xDFE1
+,0x40C0
+,0x4202
+,0x41E3
+,0x4104
+,0xBC25
+,0x31EC
+,0x41E6
+,0xBC02
+,0x08EC
+,0x41C0
+,0xBC24
+,0x87FF
+,0x4166
+,0xBC02
+,0x08F9
+,0xCFE1
+,0x4000
+,0x4402
+,0x43E3
+,0x4164
+,0xBC25
+,0x31ED
+,0x43E6
+,0xBC02
+,0x08EC
+,0xDFE5
+,0x4180
+,0xBC24
+,0xFF07
+,0x4066
+,0xBC02
+,0x08F9
+,0xCFE5
+,0x40E0
+,0xBC24
+,0xFFE0
+,0x4006
+,0xBC02
+,0x08F9
+,0x4000
+,0xBC02
+,0x0733
+,0xBC20
+,0x2098
+,0x43E1
+,0xFB11
+,0x4021
+,0xFB11
+,0x4500
+,0x4401
+,0xBC02
+,0x07CA
+,0x4140
+,0xBC21
+,0x0841
+,0xBC02
+,0x07CA
+,0xBC20
+,0x01F4
+,0x4841
+,0xBC02
+,0x07E8
+,0x4140
+,0xBC21
+,0x0840
+,0xBC02
+,0x07CA
+,0x4500
+,0x4001
+,0xBC02
+,0x07CA
+,0xBC21
+,0x2023
+,0xBC22
+,0x0400
+,0xFA31
+,0x084A
+,0x2610
+,0x8F0A
+,0x5364
+,0x4065
+,0xBC02
+,0x07F0
+,0x4AC0
+,0x4021
+,0xBC02
+,0x07CA
+,0xBC21
+,0x1FFA
+,0x8D02
+,0xBC21
+,0x1FFB
+,0x4040
+,0xBC02
+,0x07CA
+,0x4C80
+,0x4841
+,0xBC02
+,0x07E8
+,0x41E0
+,0xBC21
+,0x4042
+,0xBC02
+,0x07CA
+,0xBC02
+,0x07A4
+,0x4E80
+,0x4021
+,0xBC02
+,0x07CA
+,0x4E60
+,0xBC21
+,0x0480
+,0xBC02
+,0x07CA
+,0x5380
+,0xBC21
+,0xAB40
+,0xBC02
+,0x07CA
+,0x4102
+,0x4503
+,0xBC24
+,0x2023
+,0xBC25
+,0x0400
+,0xFA94
+,0x0925
+,0x2640
+,0x1853
+,0x53C0
+,0xBC02
+,0x07CA
+,0x4E04
+,0x4025
+,0xBC02
+,0x07FB
+,0xCFD5
+,0xE9FE
+,0x8EB8
+,0x1048
+,0x0891
+,0x08D9
+,0x2620
+,0x1863
+,0xFAB2
+,0x004A
+,0x4002
+,0x3210
+,0x1851
+,0x210E
+,0x1971
+,0x8EB8
+,0xE901
+,0x8E00
+,0xDFF5
+,0xBC02
+,0x07B8
+,0x0861
+,0x316E
+,0x0A4D
+,0xBC02
+,0x07CA
+,0xCFF5
+,0xE9FF
+,0x8EB8
+,0xBC20
+,0x209F
+,0xBC21
+,0x31DB
+,0xA300
+,0x047E
+,0xA301
+,0x047D
+,0xBD11
+,0x0911
+,0xFA22
+,0xFB02
+,0x8EC0
+,0xA300
+,0x047E
+,0xA301
+,0x047D
+,0x0000
+,0x6915
+,0xA908
+,0xA21B
+,0x0180
+,0xA21E
+,0x017E
+,0xA21D
+,0x016E
+,0xBC3C
+,0x3116
+,0xBC30
+,0x311D
+,0x7016
+,0xDF1B
+,0xA204
+,0x017F
+,0xA202
+,0x0181
+,0xA203
+,0x0182
+,0xA201
+,0x01AD
+,0x6915
+,0x1F3D
+,0x77F6
+,0x9F5E
+,0xBC26
+,0x3106
+,0xDF70
+,0xDF9C
+,0xBD08
+,0x09DB
+,0xA200
+,0x015E
+,0xBC3C
+,0x009C
+,0xBC3E
+,0x00C2
+,0xA304
+,0x017F
+,0x6E7B
+,0x9FA1
+,0x6E43
+,0xBAC5
+,0x6E4B
+,0xBE18
+,0x396C
+,0x8A0E
+,0xBF95
+,0x8A18
+,0x77E6
+,0x9FC6
+,0x6A91
+,0x7AD5
+,0x7077
+,0xFE18
+,0x6A91
+,0x4F86
+,0x88D0
+,0x6E62
+,0xFAC7
+,0x6E7A
+,0x5FE0
+,0x39C8
+,0x8890
+,0xBC3D
+,0x0170
+,0x6FCA
+,0x4F41
+,0x6910
+,0xBAC5
+,0x6910
+,0xFF38
+,0x7016
+,0xBE38
+,0x2A47
+,0x6A91
+,0xFE38
+,0xBF95
+,0x8A38
+,0x6A91
+,0x7AC7
+,0xBF95
+,0x8A38
+,0xBF9D
+,0x8E38
+,0xBF95
+,0xAA38
+,0x2A47
+,0x6A91
+,0xFE38
+,0x2A45
+,0x88D0
+,0x398B
+,0x39E9
+,0x39C8
+,0x88F0
+,0xB06C
+,0xFFFA
+,0x613E
+,0xDF86
+,0xBC26
+,0x7ADD
+,0xBCB7
+,0x8000
+,0x04AA
+,0xBC26
+,0x7ADD
+,0xBCA5
+,0x8000
+,0xA300
+,0x015E
+,0x6025
+,0x0F00
+,0x6FCB
+,0xCFC4
+,0x6036
+,0x0FE0
+,0xB048
+,0xFFF1
+,0x6910
+,0xBF38
+,0x6910
+,0xDF41
+,0xFA86
+,0x6960
+,0x3E18
+,0x8A0E
+,0xBF99
+,0x0C18
+,0x7076
+,0x9F07
+,0x6A91
+,0xBA96
+,0x7016
+,0xBE18
+,0x2A46
+,0x88E0
+,0x398B
+,0x39E9
+,0x39C8
+,0x88F0
+,0xA300
+,0x015E
+,0x7077
+,0x8F20
+,0xBC3C
+,0x0160
+,0x6FCD
+,0xCF66
+,0x6910
+,0xBF18
+,0x6910
+,0xFAC7
+,0x7147
+,0xFE18
+,0x2A47
+,0xBF9D
+,0x8E18
+,0xBF9D
+,0x8E18
+,0x2A47
+,0xBF9D
+,0x8E18
+,0xBF9D
+,0x8E18
+,0xBF9D
+,0x8E18
+,0x2A47
+,0xBF9D
+,0xAE18
+,0x2A47
+,0x88F0
+,0xB06C
+,0xFFFA
+,0x6E62
+,0xDF66
+,0x39E9
+,0x39C8
+,0x88E0
+,0x0E7A
+,0x3F3E
+,0x63EC
+,0xFF18
+,0x6FC3
+,0x8FA1
+,0xBC3D
+,0x0184
+,0xB068
+,0xFFF1
+,0x6915
+,0xBF38
+,0x6915
+,0x1F20
+,0x5FDA
+,0x3885
+,0xCF1E
+,0xCF50
+,0xA310
+,0x017E
+,0xA301
+,0x01AD
+,0xA304
+,0x017F
+,0xA302
+,0x0181
+,0xA31E
+,0x0180
+,0xA303
+,0x0182
+,0xCF3B
+,0x8EC0
+,0xE9F8
+,0xA31B
+,0x016E
+,0x0000
+,0x2451
+,0xA201
+,0x01AC
+,0x3909
+,0xBC22
+,0x3124
+,0x2453
+,0xBC3D
+,0x0184
+,0x451F
+,0xBD08
+,0x0A11
+,0x77F6
+,0xFA43
+,0x2442
+,0x6960
+,0x3E38
+,0x8A0C
+,0xBF8C
+,0x8638
+,0x2A43
+,0x88B0
+,0x398B
+,0x39E9
+,0x39C8
+,0x88C0
+,0x439B
+,0x6E18
+,0x2403
+,0xB024
+,0xFFF3
+,0x6D06
+,0xA444
+,0x6910
+,0xEA38
+,0x8EC0
+,0xA301
+,0x01AC
+,0x8E00
+,0xBC20
+,0x3131
+,0xA201
+,0x02C2
+,0xFA10
+,0x2600
+,0x8F3E
+,0xA200
+,0x01E2
+,0x2680
+,0x8F39
+,0x2610
+,0xA200
+,0x01BE
+,0xB010
+,0xFFFF
+,0x8F2C
+,0xA202
+,0x01E3
+,0x26A0
+,0x8F28
+,0xBC22
+,0x02A8
+,0xBC23
+,0x3133
+,0xBC24
+,0x3132
+,0xBC40
+,0x3906
+,0xFA73
+,0xBC25
+,0x3134
+,0xBC27
+,0x3135
+,0xBC40
+,0x3102
+,0xFA94
+,0x04F3
+,0xFAB5
+,0xFAF6
+,0x04A2
+,0x1095
+,0x10DE
+,0x1D1A
+,0x4003
+,0x3240
+,0x3843
+,0x8F02
+,0xB228
+,0x0040
+,0x4803
+,0x18DC
+,0x2103
+,0x8F05
+,0x2183
+,0x8F18
+,0x3401
+,0xA300
+,0x01BE
+,0x8D15
+,0x8C14
+,0xA301
+,0x01BE
+,0x3280
+,0x4002
+,0x8F0D
+,0xA301
+,0x01BE
+,0x8D0C
+,0x8C0B
+,0x4002
+,0x2690
+,0x4800
+,0x4002
+,0x8F03
+,0x8E00
+,0x8C04
+,0xA302
+,0x01BE
+,0xA300
+,0x01BE
+,0xA200
+,0x01BE
+,0x2600
+,0xBC21
+,0x2035
+,0x4020
+,0x8EC0
+,0x1810
+,0xFB30
+,0x0000
+,0x38E0
+,0xA200
+,0x01E1
+,0xB202
+,0x0040
+,0x405A
+,0xBC3C
+,0x01C0
+,0x441E
+,0x8F0F
+,0x6E11
+,0xE800
+,0xBD08
+,0x0A88
+,0x6D74
+,0xA103
+,0xE142
+,0x1B1A
+,0x0E9A
+,0x3F14
+,0x6E11
+,0xFF18
+,0x8E00
+,0x8EC0
+,0xA300
+,0x01E1
+,0x8E00
+,0xB522
+,0x0009
+,0x3867
+,0xBD08
+,0x0A9D
+,0x6D76
+,0xA184
+,0xE1C3
+,0xBCB6
+,0x8000
+,0x8E00
+,0x1B63
+,0x0EE3
+,0x3F1D
+,0x6E19
+,0xFF18
+,0x8E00
+,0x8EC0
+,0xA300
+,0x01E1
+,0x8E00
+,0xA200
+,0x01F7
+,0x2600
+,0xA200
+,0x01E4
+,0x8F44
+,0xA201
+,0x01F8
+,0x2690
+,0x8F41
+,0xBC21
+,0x3173
+,0xA202
+,0x01E5
+,0xFA31
+,0x2191
+,0x8F02
+,0x3491
+,0xA302
+,0x01E5
+,0xA202
+,0x01E5
+,0x2251
+,0x8F33
+,0xBC21
+,0x02A8
+,0xBC23
+,0x316F
+,0xBC25
+,0x316C
+,0xBC40
+,0x4086
+,0xFA73
+,0xBC22
+,0x316D
+,0xBC24
+,0x316E
+,0x680C
+,0xFAB3
+,0xFA52
+,0xFA94
+,0x38A3
+,0x8F04
+,0xBC23
+,0x3170
+,0x8E00
+,0xFA73
+,0x2033
+,0x18D4
+,0xBC26
+,0x3171
+,0xBC40
+,0x4881
+,0xFAD6
+,0x210E
+,0x8F04
+,0xBC25
+,0x3172
+,0x8E00
+,0xFAB5
+,0x210D
+,0x1954
+,0x1E5D
+,0x2208
+,0x401E
+,0x8F0A
+,0x2108
+,0xA31E
+,0x01E5
+,0x8F03
+,0x8E00
+,0x8C05
+,0xB000
+,0xFFFF
+,0x3401
+,0x8D01
+,0x4000
+,0x40A1
+,0x2801
+,0xA300
+,0x01E4
+,0x382E
+,0xB012
+,0x3136
+,0xBC20
+,0x3163
+,0xBD04
+,0x0AFB
+,0xFA22
+,0xFB02
+,0xFA2A
+,0xFB02
+,0xBD04
+,0x0B01
+,0xFA2A
+,0xFB02
+,0x8EB8
+,0x0000
+,0x2451
+,0xA201
+,0x01E0
+,0x3909
+,0xBC22
+,0x3163
+,0x2453
+,0xBC3D
+,0x01C0
+,0x441F
+,0xBD08
+,0x0B25
+,0x77F6
+,0xFA43
+,0x2442
+,0x6960
+,0x3E38
+,0x8A08
+,0xBF8C
+,0x8638
+,0x2A43
+,0x88B0
+,0x398B
+,0x39E9
+,0x39C8
+,0x88C0
+,0x429B
+,0x6E18
+,0x2403
+,0xB024
+,0xFFF7
+,0x6D06
+,0xA444
+,0x6910
+,0xEA38
+,0x8EC0
+,0xA301
+,0x01E0
+,0x8E00
+,0xBC20
+,0x31B2
+,0x5FE1
+,0xFA10
+,0xB020
+,0x319C
+,0xB012
+,0x319C
+,0x0008
+,0xBC23
+,0x01F9
+,0xFA10
+,0xBC40
+,0x1981
+,0x6862
+,0x3A52
+,0xBC40
+,0x3582
+,0x8F06
+,0xA200
+,0x0085
+,0x2681
+,0x8F03
+,0x8EC0
+,0x4040
+,0xA300
+,0x0085
+,0x8EB8
+,0x0000
+,0xBC21
+,0x02A8
+,0xBC23
+,0x0263
+,0xBC40
+,0x4880
+,0xBC40
+,0x5084
+,0x6E10
+,0xE580
+,0x7000
+,0x25C4
+,0xA203
+,0x0266
+,0xBC40
+,0x5881
+,0x2630
+,0xBC40
+,0x1501
+,0x401C
+,0x8F28
+,0x3820
+,0xB532
+,0x0002
+,0xB036
+,0x3174
+,0x3882
+,0x6910
+,0xBA65
+,0x6960
+,0x2206
+,0x8A02
+,0xBBD4
+,0xCA86
+,0x6A3D
+,0x7A73
+,0x88C0
+,0x3215
+,0x00E3
+,0x8F05
+,0xB416
+,0x0002
+,0x0441
+,0x3214
+,0x1801
+,0x8C0A
+,0x3B80
+,0x3330
+,0x8F04
+,0x2614
+,0x8F04
+,0x8E00
+,0x8CE1
+,0x3449
+,0x344D
+,0x8DDE
+,0xBC20
+,0x31B2
+,0x383C
+,0xFA10
+,0x2108
+,0x1801
+,0xB000
+,0x319C
+,0x8EC0
+,0xFA10
+,0xA300
+,0x01FF
+,0xBC25
+,0x01F9
+,0x34AB
+,0xE904
+,0xE143
+,0x6122
+,0xDF82
+,0x3320
+,0x8F02
+,0xBC23
+,0x31B4
+,0x8C05
+,0xFA73
+,0xBC23
+,0x31B3
+,0x8E00
+,0xFA73
+,0x2813
+,0xA201
+,0x0260
+,0xBC40
+,0x268E
+,0xBC40
+,0x2E8F
+,0x6D4A
+,0xA29E
+,0x700E
+,0xE2DC
+,0x7307
+,0xDFDE
+,0x6E7F
+,0x224C
+,0xCFCE
+,0x6A34
+,0xDFA5
+,0x6E28
+,0x2800
+,0xBC3D
+,0x0200
+,0x6EE3
+,0xE287
+,0x88E0
+,0xBD07
+,0x0BC7
+,0x6D00
+,0x9FCE
+,0xBCFF
+,0x8000
+,0x8E00
+,0xE4E7
+,0xE2C5
+,0xBCDB
+,0x8000
+,0x6E7F
+,0x0FCE
+,0x6A34
+,0xE4E5
+,0x38A0
+,0x88E0
+,0x6EE3
+,0xE287
+,0xDFCE
+,0xBCFF
+,0x8000
+,0xCF82
+,0xE4E7
+,0xE2C5
+,0xBCDB
+,0x8000
+,0xE64C
+,0xE4E5
+,0xCFDF
+,0xE546
+,0xA301
+,0x0260
+,0xA31F
+,0x01F9
+,0xCFA3
+,0x8EC0
+,0xE9FC
+,0xE5DC
+,0x0000
+,0xBC22
+,0x31B7
+,0x8E00
+,0xFA52
+,0x26A0
+,0x8F04
+,0x8EC0
+,0xBC22
+,0x6568
+,0xA302
+,0x0268
+,0xA200
+,0x0261
+,0x403A
+,0xBC3C
+,0x0200
+,0x4C1E
+,0x8E00
+,0xE062
+,0xA300
+,0x0261
+,0x6904
+,0xBC1B
+,0x241B
+,0xBD1E
+,0x0BFA
+,0x67A6
+,0xBC1B
+,0x241B
+,0x1E9A
+,0xBC3D
+,0x0290
+,0xA201
+,0x0293
+,0x3B7A
+,0x407F
+,0xBC23
+,0x31B6
+,0x6EE7
+,0x64E2
+,0xFA73
+,0xA204
+,0x02B0
+,0xA300
+,0x0261
+,0xA301
+,0x0293
+,0x21A3
+,0x8F2C
+,0xA200
+,0x0293
+,0x407E
+,0xBC23
+,0x31B5
+,0x7016
+,0xBC1C
+,0x1EA2
+,0xB800
+,0xE61C
+,0x1EA2
+,0x1E93
+,0xB124
+,0x0001
+,0xBC23
+,0x2000
+,0xBCA4
+,0xC000
+,0xBC24
+,0x3FFF
+,0x24DA
+,0xB056
+,0xFFFF
+,0x3095
+,0x0562
+,0xA300
+,0x0293
+,0x4004
+,0xBD0B
+,0x0C39
+,0x33D0
+,0xB56A
+,0x0001
+,0x8F02
+,0xB548
+,0x0001
+,0x8C05
+,0x0172
+,0x3521
+,0x0572
+,0xB548
+,0x0001
+,0x8E00
+,0x30A3
+,0xA302
+,0x0269
+,0xA202
+,0x0269
+,0xA203
+,0x0268
+,0x0493
+,0x3220
+,0xBC23
+,0x0400
+,0x8F02
+,0xBC23
+,0x31B8
+,0x8E00
+,0xFA73
+,0xBC24
+,0x0267
+,0x281A
+,0xE643
+,0x8EC0
+,0xBC40
+,0x260F
+,0xBC40
+,0x1E0E
+,0x0000
+,0xBC23
+,0x0267
+,0x349D
+,0xE904
+,0x6D57
+,0xA15F
+,0x6D27
+,0xDF82
+,0x700E
+,0xA2DD
+,0xBC40
+,0x2184
+,0x6E7F
+,0x5FDF
+,0xBC40
+,0x1983
+,0x7307
+,0xA14C
+,0xCFCE
+,0x6AA7
+,0x1FA5
+,0xA200
+,0x0262
+,0xBC3C
+,0x0200
+,0x88E0
+,0x6EEB
+,0xFC1F
+,0x6960
+,0x1FCE
+,0xBC25
+,0x026F
+,0xBCFD
+,0xC000
+,0xBD07
+,0x0C8C
+,0xB51E
+,0x0002
+,0x6D7A
+,0xA681
+,0xE061
+,0xBC9C
+,0x4000
+,0x6E7F
+,0x4FCE
+,0xB512
+,0x0002
+,0x6AA7
+,0x26C1
+,0x88E0
+,0x6E29
+,0xDFCE
+,0x6EEB
+,0xFC1F
+,0xBCFD
+,0xC000
+,0x8E00
+,0xB51E
+,0x0002
+,0xE681
+,0xE061
+,0xBC9C
+,0x4000
+,0xCFA3
+,0xB512
+,0x0002
+,0xBC24
+,0x0267
+,0xE6C1
+,0xE5DD
+,0xE54C
+,0xA300
+,0x0262
+,0xBC40
+,0x0E06
+,0xCF85
+,0xCFDE
+,0x8EC0
+,0xE9FC
+,0xE6DE
+,0xA200
+,0x02A7
+,0x2600
+,0xBC01
+,0x0D4B
+,0xA203
+,0x0294
+,0x2630
+,0xA202
+,0x02C5
+,0xBC25
+,0x1000
+,0xA200
+,0x02C6
+,0xA204
+,0x02C3
+,0xA201
+,0x01BE
+,0xBCA5
+,0x4000
+,0xBC23
+,0x0294
+,0x8F33
+,0xBC26
+,0x31CE
+,0xBC40
+,0x1185
+,0x6990
+,0x7AD4
+,0x0495
+,0xBCA5
+,0x0000
+,0xBC26
+,0x31CF
+,0x00AA
+,0xBC25
+,0x31D0
+,0xBC40
+,0x1984
+,0xBC40
+,0x2187
+,0x0404
+,0xFAD6
+,0x044F
+,0xFAB5
+,0xBC81
+,0x8000
+,0xBC93
+,0x4000
+,0x0020
+,0x0079
+,0xA204
+,0x0299
+,0xBC40
+,0x1582
+,0xBC40
+,0x1D80
+,0xBC40
+,0x2581
+,0x8F07
+,0x32C0
+,0x4000
+,0x8F00
+,0xB008
+,0xFFFF
+,0x8C13
+,0xA300
+,0x0299
+,0xBC20
+,0x4000
+,0x21A0
+,0x8F00
+,0x3421
+,0x8C0B
+,0xA300
+,0x0299
+,0x403E
+,0xBC40
+,0x1D80
+,0xA31E
+,0x0294
+,0xBC40
+,0x2581
+,0xBC40
+,0x1582
+,0xBC20
+,0x31D1
+,0xBC40
+,0x1185
+,0xFA10
+,0x20A8
+,0x4020
+,0xBC40
+,0x1981
+,0x3840
+,0x8F06
+,0xBC20
+,0x31D2
+,0x8E00
+,0xFA10
+,0x2088
+,0x3802
+,0x8F00
+,0x4000
+,0xBC24
+,0x31D3
+,0xBC40
+,0x2183
+,0xFA94
+,0xBC27
+,0x31EE
+,0x4006
+,0x6867
+,0x3AF3
+,0x1932
+,0x202B
+,0x8F04
+,0xBC23
+,0x31EF
+,0x8E00
+,0xFA73
+,0x218B
+,0x8F00
+,0x3886
+,0x2640
+,0xBC21
+,0x029A
+,0x8F0B
+,0xBC23
+,0x31D4
+,0xA204
+,0x0299
+,0xFA73
+,0x2023
+,0x8F01
+,0x2600
+,0x8F03
+,0x8E00
+,0x8C13
+,0xA306
+,0x0295
+,0xBC20
+,0x31F7
+,0xBC40
+,0x2083
+,0xFA10
+,0x2118
+,0x1803
+,0xA302
+,0x0295
+,0xBC40
+,0x1C86
+,0xBC40
+,0x1486
+,0xBC40
+,0x5C86
+,0xBC40
+,0x2480
+,0xBC40
+,0x2080
+,0xB230
+,0x7530
+,0x4C02
+,0x8EC0
+,0x1810
+,0xBC40
+,0x2480
+,0x8EC0
+,0x4000
+,0xA300
+,0x0294
+,0x0000
+,0xBC22
+,0x31F0
+,0xE91C
+,0xBC24
+,0x029A
+,0x7007
+,0x3A52
+,0x6E11
+,0x1C82
+,0x6E7F
+,0x3C85
+,0xBC26
+,0x31F4
+,0xBC23
+,0x31F3
+,0x77FE
+,0xDCA4
+,0xBC27
+,0x31F2
+,0xB801
+,0xA891
+,0x7027
+,0xFA73
+,0xFAF6
+,0xDCC3
+,0xBC27
+,0x31D5
+,0xBC23
+,0x31DA
+,0xDD26
+,0xDD04
+,0xFAF6
+,0xBC24
+,0x31F5
+,0xFA73
+,0xDD66
+,0xDD43
+,0xFA96
+,0xB074
+,0x000B
+,0xBC23
+,0x31D8
+,0xDDA6
+,0xDD87
+,0xBC26
+,0x31D7
+,0xB800
+,0xE6F7
+,0xDCE1
+,0xBC24
+,0x31D6
+,0x6D34
+,0x9DC3
+,0xDDE7
+,0xBC21
+,0x8000
+,0xFAD6
+,0xBC27
+,0x31D9
+,0xFA94
+,0x6163
+,0x9E46
+,0xE1DE
+,0x6D34
+,0xDE03
+,0x6143
+,0x1E24
+,0xDE86
+,0xDE63
+,0xB801
+,0xEE73
+,0xB064
+,0x000C
+,0xBC21
+,0x31F6
+,0xDEA7
+,0xDEE3
+,0xDF06
+,0xBC27
+,0x31F1
+,0xB034
+,0x0009
+,0x6D45
+,0x1EC4
+,0xB800
+,0x6CD1
+,0x6E81
+,0xBAF6
+,0xB024
+,0x000A
+,0xDFA6
+,0xDF42
+,0xDF23
+,0xE1C3
+,0xE142
+,0xE246
+,0xDF64
+,0xDF8F
+,0xBC3D
+,0x029F
+,0xBD08
+,0x0E56
+,0x6CD8
+,0x1FC1
+,0x7003
+,0x0E27
+,0x6915
+,0xA044
+,0x8F01
+,0x2640
+,0x8F6F
+,0x6A3B
+,0xCCE5
+,0x6D6C
+,0x4EC7
+,0x6A3B
+,0xDFE6
+,0x88D0
+,0xB20C
+,0x0060
+,0xDCE5
+,0xCDC5
+,0x8F65
+,0x6A09
+,0x4D65
+,0x88FC
+,0x6910
+,0x8C86
+,0x28DD
+,0x28FD
+,0x8890
+,0xBCFF
+,0xC000
+,0xBC92
+,0x4000
+,0x2442
+,0x28D5
+,0x6A3F
+,0x4CE5
+,0x88F0
+,0x686B
+,0x8D26
+,0x611E
+,0x4DE7
+,0x2409
+,0x8F05
+,0xCFA6
+,0x686B
+,0x8CC5
+,0xCD06
+,0x666B
+,0x8CE5
+,0x6113
+,0x5DFC
+,0x2409
+,0x32F0
+,0xBCEC
+,0x4000
+,0x8F05
+,0xCD41
+,0x686E
+,0x5DFC
+,0x8F01
+,0x35F9
+,0xDDE7
+,0x686D
+,0x4EE6
+,0x401F
+,0x8F12
+,0x6CB8
+,0x0DC5
+,0x3BBC
+,0x8F09
+,0x38FE
+,0xBC21
+,0x2666
+,0xBCFE
+,0x4000
+,0xB06C
+,0xFFFF
+,0x3BA6
+,0x3BE7
+,0x0F27
+,0x6EF7
+,0xDEFD
+,0xBC3D
+,0x029F
+,0x8C26
+,0x409F
+,0xCDE5
+,0x69B4
+,0x0EA6
+,0x8F01
+,0x3569
+,0xDDE5
+,0x684B
+,0x9EFC
+,0x7027
+,0xCDC5
+,0xBC3D
+,0x029F
+,0x8F16
+,0x6910
+,0x8FC1
+,0x5BE5
+,0x28E5
+,0xBC25
+,0x31CA
+,0x403B
+,0xFAA6
+,0xE0E7
+,0x8A03
+,0xBBF9
+,0x4C3F
+,0x6A3F
+,0x9EF0
+,0x88D0
+,0x77FE
+,0xDFC1
+,0x66EB
+,0x0DC5
+,0x0F26
+,0x3BC6
+,0x8D02
+,0xDFE6
+,0xCDC5
+,0x6A09
+,0x4E47
+,0x88EC
+,0x6915
+,0x0F8F
+,0x6915
+,0x8E85
+,0x28F7
+,0x28DD
+,0x88B0
+,0xBC9D
+,0x8000
+,0xBCE6
+,0xC000
+,0x6915
+,0x0F8F
+,0x2456
+,0x6A33
+,0xCFC1
+,0x28D5
+,0x88A0
+,0x8E00
+,0x0556
+,0x242D
+,0x26D0
+,0x8F04
+,0xCFE6
+,0xCDA7
+,0x2137
+,0x19BE
+,0xDFE6
+,0x6D00
+,0xA444
+,0x6915
+,0xEA38
+,0xE4C4
+,0xCFE6
+,0xCF44
+,0xCF27
+,0xCF00
+,0xE7C3
+,0xE642
+,0xA305
+,0x029A
+,0xCE02
+,0xCD83
+,0xCF65
+,0xE441
+,0xCDE7
+,0xCE64
+,0xCEFB
+,0xCCF0
+,0xCCA1
+,0xE9E4
+,0xE6C6
+,0xE5C7
+,0xE55E
+,0x8EC0
+,0xE65B
+,0xE4D0
+,0xBC21
+,0x02A8
+,0xE90E
+,0x6E18
+,0x7C22
+,0xA204
+,0x02C4
+,0x6C28
+,0xA0C5
+,0xA200
+,0x02C2
+,0x6C49
+,0x5F04
+,0xB050
+,0x31BD
+,0x6E0D
+,0x1F55
+,0x6980
+,0x3AB6
+,0xB012
+,0xFFF2
+,0xA21E
+,0x02C6
+,0xB000
+,0x31BF
+,0x616C
+,0xA4DE
+,0x7000
+,0x5F21
+,0xFA12
+,0x4025
+,0x180D
+,0x0554
+,0xB020
+,0x31BB
+,0xA204
+,0x02C5
+,0xBC40
+,0x2187
+,0x31E7
+,0xFA52
+,0x0497
+,0xB000
+,0x31B9
+,0xBC40
+,0x1987
+,0x3127
+,0x6C88
+,0x3A10
+,0x0504
+,0x38F4
+,0xB00E
+,0xFFF7
+,0x6622
+,0x9F60
+,0x6D37
+,0x6446
+,0xB06E
+,0xFFF6
+,0x6C90
+,0x1F86
+,0x6643
+,0x2745
+,0xB05E
+,0xFFF5
+,0xB07E
+,0xFFF4
+,0xE1C6
+,0x6998
+,0x66C4
+,0xE7C2
+,0xDFC7
+,0xDFA5
+,0x8F54
+,0xBC20
+,0x02A8
+,0x700F
+,0x8E44
+,0x65E3
+,0x0EC5
+,0xB5A8
+,0x000F
+,0x65B3
+,0x65DE
+,0xBC40
+,0xBC02
+,0xBC40
+,0x5404
+,0xB4AA
+,0x0001
+,0xB5B6
+,0x000F
+,0xB4C8
+,0x0001
+,0xB5EC
+,0x000F
+,0x62B6
+,0x8EA2
+,0x0BB4
+,0x170A
+,0xBC40
+,0xC406
+,0xB4E4
+,0x0001
+,0xB5C8
+,0x000F
+,0xBC40
+,0x9403
+,0x62C9
+,0x8E83
+,0x178B
+,0xB4F6
+,0x0001
+,0xB5EC
+,0x000F
+,0x0BB7
+,0xBC40
+,0x8404
+,0xCEE4
+,0xB5FA
+,0x000F
+,0xBC40
+,0x4405
+,0x174C
+,0xBC40
+,0x8C07
+,0xB4F8
+,0x0001
+,0xB5DA
+,0x000F
+,0xBC40
+,0x3C02
+,0xBC40
+,0x4C03
+,0xB5A4
+,0x000F
+,0xB5B6
+,0x000F
+,0xBC40
+,0x3404
+,0x0B6F
+,0xB5C8
+,0x000F
+,0xBC40
+,0x7C02
+,0xBC40
+,0x9C03
+,0xBC40
+,0x5C01
+,0xBC40
+,0xAC01
+,0xBC40
+,0xB401
+,0xBC40
+,0x7405
+,0xBC40
+,0xA406
+,0x8C69
+,0xA304
+,0x02B5
+,0xBC23
+,0x02B5
+,0xBC22
+,0x31C4
+,0xB046
+,0xFFF9
+,0xFA52
+,0xDFE4
+,0xBC02
+,0x1E36
+,0x7000
+,0x4FE0
+,0xB030
+,0x000B
+,0xBC20
+,0x31C3
+,0xB046
+,0xFFF7
+,0xFA12
+,0xCF80
+,0xDF84
+,0xBC02
+,0x1E36
+,0x7000
+,0x4F80
+,0x6D31
+,0xCFA0
+,0xBC22
+,0x31C6
+,0xB046
+,0xFFF8
+,0xFA52
+,0xDF84
+,0xBC02
+,0x1E36
+,0x7000
+,0x4F80
+,0xB030
+,0x000C
+,0xBC20
+,0x31C5
+,0xB046
+,0xFFF6
+,0xFA12
+,0xCFC0
+,0xDF84
+,0xBC02
+,0x1E36
+,0x6E05
+,0x0F81
+,0xB032
+,0x000E
+,0xBC40
+,0x788F
+,0x7000
+,0x61CE
+,0xB040
+,0xFFF3
+,0x88D8
+,0xBC22
+,0x31C7
+,0xB066
+,0xFFF3
+,0xCF20
+,0xFA52
+,0xDE65
+,0xDF26
+,0xDF83
+,0xBC02
+,0x1E36
+,0xCF80
+,0xCF01
+,0xBC47
+,0xA803
+,0xBC47
+,0x5804
+,0x6112
+,0xCE7E
+,0x6C33
+,0x0F21
+,0x241B
+,0xBC47
+,0xA004
+,0x6847
+,0x24DE
+,0xDEE3
+,0x8F03
+,0xBC23
+,0x31C9
+,0x4001
+,0x8C05
+,0xFA72
+,0xBC23
+,0x31C8
+,0x4001
+,0xFA72
+,0xB030
+,0xFFFE
+,0xB046
+,0xFFF6
+,0xCF60
+,0xBC02
+,0x1E36
+,0xBC21
+,0x02A8
+,0xBC20
+,0x31C1
+,0xCF1E
+,0xBC40
+,0x4083
+,0xFA10
+,0xBC40
+,0x649E
+,0x2098
+,0x8F09
+,0xBC20
+,0x31C2
+,0xBC40
+,0x5083
+,0xFA10
+,0x6406
+,0x0F55
+,0x0018
+,0x8C03
+,0xBC40
+,0x5480
+,0xCF55
+,0x8E00
+,0x8EC0
+,0xE9F2
+,0x8E00
+,0xBC23
+,0x00A5
+,0xBC20
+,0x3054
+,0x6E10
+,0xE181
+,0xB800
+,0x2074
+,0x24A1
+,0xA201
+,0x045F
+,0x28C8
+,0x6911
+,0x2902
+,0xBC21
+,0x00A3
+,0x6E10
+,0x654E
+,0xBC24
+,0x2081
+,0xE085
+,0xBC26
+,0x2083
+,0xB801
+,0x2837
+,0x692F
+,0x65CF
+,0xDFC3
+,0xFAD3
+,0x28D8
+,0x2444
+,0xBC23
+,0x00A1
+,0x6E10
+,0xE54E
+,0xE185
+,0xE1C6
+,0x692D
+,0x64CF
+,0x28E0
+,0x2444
+,0xA200
+,0x00A0
+,0x7008
+,0xA54E
+,0x6220
+,0xA5CF
+,0xBC24
+,0x2080
+,0x26A0
+,0xFA94
+,0xBC22
+,0x00A7
+,0x8F0E
+,0x38A2
+,0x8E00
+,0xE286
+,0xE2C7
+,0x24BE
+,0xBC26
+,0x3055
+,0x8E00
+,0xFAD6
+,0x28E6
+,0x2444
+,0x8E00
+,0xA30E
+,0x00A7
+,0xE6CF
+,0xBC24
+,0x3053
+,0x8E00
+,0xFA94
+,0x2244
+,0x8F3A
+,0x7007
+,0x8FC4
+,0xA20E
+,0x00A5
+,0xE24F
+,0x88C8
+,0xA20E
+,0x00A1
+,0x690B
+,0x21CF
+,0x88B8
+,0xA20E
+,0x00A3
+,0xE0CF
+,0x8898
+,0xBC26
+,0x3056
+,0xE10E
+,0xFAD6
+,0x6807
+,0xA14F
+,0x88A8
+,0x8F10
+,0xBC26
+,0x3057
+,0x8E00
+,0xFAD6
+,0x200E
+,0x8F0A
+,0xBC26
+,0x3059
+,0x8E00
+,0xFAD6
+,0x212E
+,0x8F04
+,0xBC25
+,0x3058
+,0x8E00
+,0xFAB5
+,0x2095
+,0x8F03
+,0x8E00
+,0x8C06
+,0xA31E
+,0x008C
+,0x403E
+,0x8E00
+,0xA31E
+,0x008C
+,0x403C
+,0xA303
+,0x009C
+,0xA301
+,0x009D
+,0xA304
+,0x009E
+,0xA302
+,0x009F
+,0xA31C
+,0x008B
+,0xE9FE
+,0x8EC0
+,0x3401
+,0xA300
+,0x00A0
+,0x6C84
+,0xA904
+,0xFA13
+,0x6E0D
+,0x1FD5
+,0xBC22
+,0x3104
+,0xB002
+,0xFFFD
+,0xFA52
+,0xBC21
+,0x7FFF
+,0x6622
+,0xA443
+,0x40A1
+,0xBC23
+,0x02CE
+,0xBC24
+,0x045A
+,0xBC02
+,0x1E36
+,0xCFD5
+,0x8E00
+,0x8EC0
+,0xE9FC
+,0x8E00
+,0xE906
+,0xA202
+,0x02D3
+,0x6E0D
+,0x1F81
+,0xB012
+,0xFFFB
+,0x6988
+,0x5FA1
+,0xDFD5
+,0x8F04
+,0xBC20
+,0x2080
+,0x4021
+,0x8C0F
+,0xA301
+,0x02D3
+,0xFA11
+,0xBC02
+,0x1E46
+,0xA201
+,0x0474
+,0x1A41
+,0x7007
+,0x9F61
+,0xBC20
+,0x2080
+,0xA31E
+,0x02D3
+,0xFB11
+,0x7040
+,0x4F83
+,0xBC22
+,0x3104
+,0x6C8C
+,0xBA10
+,0xFA52
+,0xBC23
+,0x7FFF
+,0x6626
+,0x9F60
+,0xCFA0
+,0xBC23
+,0x02D1
+,0xBC24
+,0x045B
+,0xBC02
+,0x1E36
+,0xCFD5
+,0x8E00
+,0x8EC0
+,0xE9FA
+,0x8E00
+,0xE902
+,0xFA31
+,0xDFC0
+,0xDFF5
+,0xBC02
+,0x1E46
+,0xCFC1
+,0xDFC0
+,0xFA31
+,0xBC02
+,0x1E46
+,0xCFC1
+,0x1A48
+,0xA200
+,0x02D5
+,0xA202
+,0x045C
+,0x0E41
+,0x26A0
+,0xA301
+,0x02D5
+,0x8F06
+,0xBC21
+,0x2082
+,0x401E
+,0xA200
+,0x02D5
+,0xA31E
+,0x02D5
+,0xFB30
+,0x6D14
+,0x4FF5
+,0xE9FE
+,0x40E0
+,0x8EC0
+,0x0848
+,0xA301
+,0x045C
+,0x6C84
+,0xBA10
+,0xE904
+,0xB580
+,0x0002
+,0xA201
+,0x0474
+,0xB100
+,0x00BE
+,0xBC23
+,0x2081
+,0x66C2
+,0x1FD5
+,0xBC22
+,0x3104
+,0x6E2D
+,0x3B74
+,0xB00A
+,0xFFFD
+,0xFA52
+,0xBC23
+,0x7FFF
+,0x6626
+,0xA444
+,0x40C1
+,0xBC23
+,0x02D6
+,0xBC24
+,0x045D
+,0xBC02
+,0x1E36
+,0xCFD5
+,0x8E00
+,0x8EC0
+,0xE9FC
+,0x8E00
+,0xE904
+,0xFA10
+,0x6E08
+,0x1FC1
+,0xDFF5
+,0xBC02
+,0x1E46
+,0xA201
+,0x0474
+,0xBC22
+,0x3104
+,0x6692
+,0x0FC0
+,0xBC23
+,0x2083
+,0x6C80
+,0xBA52
+,0xBC24
+,0x7FFF
+,0x6E05
+,0x3B71
+,0x6628
+,0x9FA1
+,0xB000
+,0xFFFD
+,0x40E1
+,0xBC23
+,0x02D9
+,0xBC24
+,0x045E
+,0xBC02
+,0x1E36
+,0xCFF5
+,0x8E00
+,0x8EC0
+,0xE9FC
+,0x8E00
+,0x0000
+,0xBC21
+,0x00A9
+,0x4402
+,0xE083
+,0xE0C4
+,0x24A3
+,0xBC23
+,0x213F
+,0x8E00
+,0x6960
+,0x3A74
+,0x8A0E
+,0x6A38
+,0xBA74
+,0xB300
+,0x0044
+,0x28E2
+,0x8F0B
+,0x2600
+,0x8F04
+,0x2444
+,0x8EC0
+,0xA30E
+,0x00A9
+,0xE4CF
+,0x4000
+,0x8EC0
+,0xA300
+,0x00A9
+,0xE4C0
+,0x8880
+,0x8EC0
+,0x8E00
+,0xA300
+,0x045F
+,0xE904
+,0xBC21
+,0x2022
+,0x6E05
+,0x1FD5
+,0xA21C
+,0x047A
+,0xB000
+,0xFFFD
+,0xFA35
+,0x7000
+,0x6445
+,0xDFFC
+,0xBC22
+,0x0780
+,0xBC23
+,0x02DD
+,0xBC24
+,0x02DF
+,0xBC02
+,0x1E36
+,0xA201
+,0x02DF
+,0xA200
+,0x02DC
+,0xCFE2
+,0xA092
+,0x8000
+,0xB000
+,0xFFFF
+,0xA301
+,0x047A
+,0x2680
+,0xA300
+,0x02DC
+,0x8F34
+,0xBC20
+,0x304D
+,0xBC3E
+,0x0320
+,0xBC3A
+,0x7FFF
+,0xFA10
+,0xA202
+,0x047C
+,0xA31E
+,0x02DC
+,0xA31A
+,0x047A
+,0x21C8
+,0x8F14
+,0xBC20
+,0x304E
+,0xBC23
+,0x304F
+,0xFA10
+,0x6872
+,0x3A70
+,0x8F03
+,0x2048
+,0x8F01
+,0x26A0
+,0x8F05
+,0x21C8
+,0x8F0A
+,0x4000
+,0xA300
+,0x047C
+,0x8D07
+,0x4040
+,0x8C05
+,0xA300
+,0x047C
+,0x4020
+,0xA300
+,0x047C
+,0xA200
+,0x047C
+,0x2242
+,0x4000
+,0x8F02
+,0xA300
+,0x047B
+,0x8C07
+,0xCFD5
+,0x7008
+,0x0FD5
+,0x8C03
+,0xA300
+,0x047B
+,0xCFD5
+,0x8E00
+,0x8EC0
+,0xE9FC
+,0x8E00
+,0xBC20
+,0x2021
+,0xA201
+,0x047C
+,0x6984
+,0x3A12
+,0x8F1B
+,0x2611
+,0xB034
+,0xFFE0
+,0x8F10
+,0x2692
+,0x8F1B
+,0xBC21
+,0x3051
+,0x8E00
+,0xFA31
+,0x20D1
+,0x8F00
+,0xA026
+,0x4000
+,0x21D1
+,0x8F11
+,0xB024
+,0x0020
+,0xA0A4
+,0x4000
+,0x8D0E
+,0xBC21
+,0x3052
+,0x8E00
+,0xFA31
+,0x8C09
+,0xA026
+,0x4000
+,0xBC21
+,0x3050
+,0xB024
+,0x0020
+,0xFA31
+,0xA0A4
+,0x4000
+,0x8EC0
+,0xFB12
+,0x8E00
+,0x0000
+,0xBC22
+,0x3105
+,0xE902
+,0xA21C
+,0x0326
+,0x77FE
+,0xBA52
+,0x6EF0
+,0x9FDC
+,0xA200
+,0x0312
+,0xBC3C
+,0x02E0
+,0xBC22
+,0x30C2
+,0xBC23
+,0x8EE4
+,0xBC24
+,0x771E
+,0xBC25
+,0x88E2
+,0x403B
+,0x706F
+,0xE800
+,0xBD05
+,0x11DA
+,0x6E30
+,0xBC19
+,0x2442
+,0x6960
+,0x3AC7
+,0x8A08
+,0xBB3D
+,0x8E19
+,0x28CF
+,0xA207
+,0x0315
+,0xBC21
+,0x12EB
+,0xA206
+,0x0316
+,0x28F9
+,0x28F3
+,0xA307
+,0x0316
+,0x88F0
+,0x2442
+,0x28FC
+,0x28F5
+,0xA307
+,0x0315
+,0x417A
+,0x88E0
+,0xA207
+,0x0317
+,0x699C
+,0xEA18
+,0x2442
+,0x4001
+,0x8F00
+,0xB01E
+,0xFFFF
+,0x6A3C
+,0x4FC1
+,0x88E4
+,0xBC3D
+,0x0318
+,0x5FFA
+,0x7007
+,0x64E6
+,0xA206
+,0x0317
+,0x6998
+,0xDFC1
+,0x8F02
+,0x35B1
+,0x3BA6
+,0x8E00
+,0xA31D
+,0x0317
+,0xA300
+,0x0312
+,0xCFC2
+,0x8EC0
+,0xE9FE
+,0xA302
+,0x0326
+,0x0000
+,0xA200
+,0x0325
+,0xA201
+,0x0354
+,0xBC3D
+,0x0327
+,0x459F
+,0x403B
+,0xBC3C
+,0x0318
+,0x41BE
+,0xBC22
+,0x30CB
+,0xBD05
+,0x1200
+,0x5FFA
+,0x3862
+,0x6910
+,0xBC1D
+,0x6960
+,0x3A64
+,0x8A03
+,0xBBB0
+,0xC81D
+,0x28EC
+,0x88B0
+,0x40DA
+,0xE4E3
+,0xEA18
+,0xA300
+,0x0325
+,0xA200
+,0x0353
+,0x3B9D
+,0x459E
+,0xBC22
+,0x30CF
+,0x5FFA
+,0xA301
+,0x0354
+,0x6910
+,0xBA43
+,0xE064
+,0x8A27
+,0xBB8C
+,0x861C
+,0x403A
+,0x28E3
+,0x88A0
+,0xEA18
+,0x8EC0
+,0xA300
+,0x0353
+,0xA302
+,0x0355
+,0xBC25
+,0x0357
+,0xBC22
+,0x30F8
+,0x6E09
+,0x7CA4
+,0xB800
+,0xA6B6
+,0x24B4
+,0xA206
+,0x0356
+,0x33B0
+,0x4FE4
+,0xBC27
+,0x01FF
+,0x35B1
+,0x1927
+,0x09F4
+,0xBC24
+,0x0100
+,0x4806
+,0x1926
+,0xA206
+,0x0355
+,0x2670
+,0xA307
+,0x0356
+,0x243E
+,0x28FC
+,0x2444
+,0x4004
+,0x7008
+,0x64CE
+,0x6673
+,0x26CF
+,0x2670
+,0x8F2C
+,0xBC27
+,0x30F7
+,0xE2CF
+,0xFAF7
+,0x6CDC
+,0x26C4
+,0xA20E
+,0x0357
+,0xA304
+,0x0357
+,0x88D8
+,0x8F1C
+,0x3230
+,0x8F01
+,0xB036
+,0xFFFF
+,0xFB53
+,0xA202
+,0x0359
+,0x2620
+,0x8F0D
+,0x2622
+,0x4043
+,0x8F05
+,0xB20A
+,0x099A
+,0x189A
+,0xB22A
+,0x21EC
+,0x8C08
+,0x18A2
+,0xB22A
+,0x13D7
+,0x8C04
+,0x188A
+,0xB20A
+,0x17AE
+,0x188A
+,0x8C07
+,0xA302
+,0x0359
+,0xBC22
+,0x30F7
+,0xB03E
+,0xFFFF
+,0xFB53
+,0xA202
+,0x0359
+,0x144A
+,0x2442
+,0x28F1
+,0x8894
+,0x8EC0
+,0x8E00
+,0xE441
+,0xBC22
+,0x2131
+,0xBC23
+,0x00B0
+,0xBC24
+,0x2135
+,0x6915
+,0x3B53
+,0xFA93
+,0xBC22
+,0x2136
+,0xE4C3
+,0xB800
+,0xA210
+,0xBC80
+,0x4000
+,0x6915
+,0xE902
+,0xBC21
+,0x30F9
+,0xA203
+,0x035B
+,0xBC22
+,0x035C
+,0x6E73
+,0xFA31
+,0xBC24
+,0x30FA
+,0x28C1
+,0xA300
+,0x035B
+,0xFA94
+,0x6E08
+,0xBC40
+,0x6A37
+,0x2143
+,0x2A83
+,0x88C0
+,0xDFCE
+,0xDFEF
+,0xBC20
+,0x0A30
+,0xBC88
+,0x0000
+,0xCFCE
+,0xA300
+,0x035A
+,0xCFEF
+,0x2444
+,0xA203
+,0x035E
+,0xB580
+,0x0001
+,0x6000
+,0xE4CE
+,0xB000
+,0x2000
+,0xE54F
+,0xA300
+,0x035E
+,0xBC21
+,0x3244
+,0xBC80
+,0x4000
+,0xBC21
+,0x2111
+,0x8EC0
+,0xE9FE
+,0xFB30
+,0xBC22
+,0x3105
+,0xBC24
+,0x30FB
+,0xE906
+,0xA203
+,0x035A
+,0xBC25
+,0xF000
+,0xFA52
+,0xFA94
+,0xA21E
+,0x0314
+,0xA21C
+,0x015F
+,0x66BA
+,0xDF84
+,0xDFA2
+,0x7050
+,0xDF63
+,0xDFDC
+,0xDF5E
+,0xBC22
+,0x0CCD
+,0xBC24
+,0x2131
+,0xBC25
+,0x199A
+,0xBC3B
+,0x009C
+,0xBC3D
+,0x02E0
+,0xBD0A
+,0x131D
+,0xA206
+,0x035F
+,0x700E
+,0x8F67
+,0x63ED
+,0xCFBE
+,0xB47C
+,0x000E
+,0xB11E
+,0x0005
+,0xA200
+,0x0360
+,0x0E08
+,0x2810
+,0xB5FE
+,0x000E
+,0x380E
+,0x1BB7
+,0xB000
+,0x0400
+,0xBCF0
+,0xC000
+,0xA306
+,0x035F
+,0xBCED
+,0x4000
+,0x283A
+,0xA307
+,0x0360
+,0x888C
+,0xBC27
+,0x00B1
+,0x6EE7
+,0x7B97
+,0x606C
+,0x0F40
+,0xBC27
+,0x3244
+,0xBCED
+,0xC000
+,0x7016
+,0xBC1F
+,0x6EE6
+,0xDF40
+,0xBC20
+,0x2135
+,0xBC21
+,0x2111
+,0xFA10
+,0xBC8E
+,0x0000
+,0xFB36
+,0xB560
+,0x0001
+,0xCF80
+,0xBC8C
+,0x0000
+,0xBC3E
+,0x00C2
+,0x63E1
+,0x8FC0
+,0x3F3E
+,0xFF18
+,0xDFC0
+,0xCFC2
+,0xA302
+,0x015F
+,0xCF43
+,0x8EC0
+,0xE9FA
+,0xA303
+,0x0314
+,0xA203
+,0x0366
+,0x6D06
+,0x6044
+,0xBC22
+,0x0367
+,0xA203
+,0x0363
+,0x08C3
+,0xA206
+,0x0355
+,0x6E00
+,0xBC45
+,0xBCC9
+,0x8000
+,0x698C
+,0x2146
+,0x24B5
+,0xA205
+,0x0364
+,0x28E5
+,0x2444
+,0xA303
+,0x0366
+,0x7000
+,0x244E
+,0x7008
+,0xE54F
+,0x1918
+,0x2640
+,0x8F4A
+,0xE14F
+,0xA20E
+,0x0367
+,0xE540
+,0xA300
+,0x0367
+,0xBC22
+,0x3101
+,0xE0C1
+,0x2409
+,0xFA52
+,0x88C8
+,0x218A
+,0x240C
+,0x3840
+,0x8F0B
+,0xBC20
+,0x2004
+,0x8E00
+,0xFA10
+,0x2680
+,0x3802
+,0x8F04
+,0xBC20
+,0x3100
+,0x5FE4
+,0xFA10
+,0x2108
+,0x181C
+,0xA201
+,0x0369
+,0xA204
+,0x0365
+,0x3449
+,0x084C
+,0xBC24
+,0x30FE
+,0x2610
+,0xA301
+,0x0369
+,0xA201
+,0x0362
+,0xFA94
+,0x195A
+,0x0048
+,0x3340
+,0x8F12
+,0x2650
+,0x8F14
+,0xBC20
+,0x3103
+,0xA204
+,0x0361
+,0x69B0
+,0x3A10
+,0x8F02
+,0x2188
+,0x8C04
+,0x185A
+,0x0410
+,0x2088
+,0x1853
+,0xA301
+,0x0361
+,0x3822
+,0x8D05
+,0xBC20
+,0x30FE
+,0xB028
+,0xFFFF
+,0xFB12
+,0x8EC0
+,0xA301
+,0x0362
+,0x8E00
+,0x8EB8
+,0xBC20
+,0x303D
+,0x4021
+,0xFA10
+,0xA202
+,0x0462
+,0x1408
+,0x3491
+,0xB000
+,0xFFFF
+,0x0810
+,0x2680
+,0xA300
+,0x0462
+,0xA200
+,0x0460
+,0x8F36
+,0xBC23
+,0x3041
+,0xBC22
+,0x3040
+,0x6980
+,0x3A73
+,0xA204
+,0x045B
+,0xA21C
+,0x045A
+,0xFA52
+,0x8F06
+,0x21A3
+,0x8F02
+,0x387C
+,0x201A
+,0x8F07
+,0x4000
+,0x8D06
+,0x21A3
+,0x8F03
+,0x387C
+,0x219A
+,0x8F00
+,0x3801
+,0xBC22
+,0x3043
+,0x8E00
+,0xFA52
+,0x2620
+,0x8F17
+,0xA202
+,0x0465
+,0x26A0
+,0x8F12
+,0xBC22
+,0x2004
+,0x8E00
+,0xFA52
+,0x26A0
+,0x8F0C
+,0xBC22
+,0x303F
+,0xA203
+,0x045E
+,0xFA52
+,0x209A
+,0x8F05
+,0xBC22
+,0x303E
+,0xA203
+,0x045D
+,0xFA52
+,0x211A
+,0x8F00
+,0x4000
+,0xBC22
+,0x3044
+,0xA300
+,0x0460
+,0xFA50
+,0xA202
+,0x0463
+,0x2680
+,0x8F03
+,0x4000
+,0x8C42
+,0xA300
+,0x0461
+,0xBC20
+,0x2015
+,0xBC23
+,0x3048
+,0xFA10
+,0xFA73
+,0x2003
+,0x4000
+,0x3860
+,0x8F1A
+,0xBC20
+,0x2080
+,0xBC24
+,0x3046
+,0xFA10
+,0xFA94
+,0x2184
+,0x3803
+,0x8F07
+,0xBC20
+,0x3047
+,0xBC24
+,0x2015
+,0xFA10
+,0xFA94
+,0x2020
+,0x3803
+,0x8F08
+,0xBC20
+,0x2083
+,0xBC24
+,0x3045
+,0xFA10
+,0xFA94
+,0x2004
+,0x3803
+,0x8F00
+,0x3801
+,0x2680
+,0x8F02
+,0xBC20
+,0x304A
+,0x8C05
+,0xFA10
+,0xBC20
+,0x3049
+,0x8E00
+,0xFA10
+,0xBC24
+,0x304B
+,0x0E10
+,0xFA92
+,0x2102
+,0x8F04
+,0xBC22
+,0x304C
+,0x8E00
+,0xFA52
+,0x2002
+,0x1890
+,0x33A0
+,0x180B
+,0xA300
+,0x0461
+,0xBC20
+,0x3042
+,0xA201
+,0x0461
+,0xA203
+,0x0460
+,0xB512
+,0x0001
+,0xFA10
+,0xA302
+,0x0463
+,0x0059
+,0x2600
+,0x8F0A
+,0x2601
+,0x8F07
+,0x2602
+,0x4042
+,0x8F02
+,0x2603
+,0x8C04
+,0x1851
+,0x8C02
+,0x4001
+,0x4021
+,0xBC20
+,0x200D
+,0x8EC0
+,0x8E00
+,0xFB11
+,0xBC20
+,0x0375
+,0xBC21
+,0x0372
+,0xBC22
+,0x036A
+,0xBC3C
+,0x0376
+,0x700E
+,0xA0C1
+,0x70CF
+,0xA040
+,0xBC23
+,0x038F
+,0xBC09
+,0x1482
+,0x2442
+,0xE104
+,0xBC26
+,0x1180
+,0x6A39
+,0xA185
+,0xBC21
+,0xF2C0
+,0x6A3A
+,0x61C7
+,0x6A3F
+,0xA5A5
+,0xE584
+,0xE184
+,0xE185
+,0xBC21
+,0x1CF0
+,0x6A3A
+,0x61C7
+,0xBC21
+,0x8620
+,0x6A3E
+,0x65A5
+,0x88C0
+,0x2442
+,0x6A39
+,0xA584
+,0xBC21
+,0x0840
+,0x6A3A
+,0x6184
+,0x6A3F
+,0xA185
+,0xBC21
+,0x0A40
+,0x6A3A
+,0x61C7
+,0xBC21
+,0x8620
+,0x6A3E
+,0x65A5
+,0x88C0
+,0x8E00
+,0xE584
+,0xE464
+,0xBC23
+,0x038F
+,0xBC21
+,0x0375
+,0x8E00
+,0xE4C0
+,0x8EB8
+,0x0000
+,0xA202
+,0x0372
+,0xA203
+,0x0395
+,0x009A
+,0xB214
+,0x0014
+,0x8F16
+,0xB024
+,0xFFEC
+,0x5FC3
+,0x04DA
+,0x3B43
+,0xA200
+,0x0375
+,0xBC3C
+,0x0376
+,0x433E
+,0xBC23
+,0x305B
+,0x77F6
+,0xAA18
+,0x6910
+,0xBA64
+,0xE065
+,0x8A05
+,0xBBB0
+,0xC81D
+,0x4023
+,0x8880
+,0xA303
+,0x0373
+,0x8EC0
+,0xA302
+,0x0395
+,0x8E00
+,0xBC20
+,0x03BA
+,0xA203
+,0x03B9
+,0x6D20
+,0xA00E
+,0xB206
+,0x0080
+,0xE04F
+,0xE14C
+,0x8F36
+,0x88B0
+,0x40A4
+,0xB226
+,0x01B0
+,0x40C5
+,0x1925
+,0x401C
+,0xB226
+,0x06C0
+,0x7007
+,0xA45C
+,0x4083
+,0x6607
+,0x255E
+,0xA205
+,0x0396
+,0xA202
+,0x03BE
+,0xA31C
+,0x03B9
+,0xA31C
+,0x03BA
+,0x2268
+,0x8F03
+,0x8E00
+,0x8C03
+,0xB034
+,0xFFFF
+,0x34D1
+,0xA300
+,0x0396
+,0xA202
+,0x03BD
+,0xB236
+,0x000A
+,0x8F05
+,0xB226
+,0xFFF6
+,0x3B83
+,0x8F04
+,0x4002
+,0x401C
+,0x8D02
+,0x4022
+,0x401C
+,0x26A1
+,0x8F00
+,0x40A0
+,0xA31C
+,0x03BE
+,0xA302
+,0x03BD
+,0x8C0D
+,0xA300
+,0x0397
+,0x2421
+,0xBC25
+,0x1000
+,0x28E5
+,0x34D9
+,0xA303
+,0x03B9
+,0xA30E
+,0x03BA
+,0xE44F
+,0xE54C
+,0xA200
+,0x0397
+,0x3048
+,0xBC20
+,0x7E7E
+,0x8EC0
+,0xBC82
+,0x0000
+,0x8E00
+,0xBC22
+,0x2131
+,0xBC24
+,0x00B2
+,0x77F6
+,0xBB54
+,0xBC23
+,0x2135
+,0xBC22
+,0x2136
+,0x7087
+,0xBA73
+,0x6910
+,0xFA52
+,0xBCB2
+,0xC000
+,0xBCA2
+,0x8000
+,0xA200
+,0x03A6
+,0x3F1A
+,0xBC22
+,0x3060
+,0xBC3C
+,0x03A8
+,0x6910
+,0xBF10
+,0xE902
+,0xFA43
+,0x6960
+,0x3E18
+,0x8A06
+,0xBF8C
+,0x8618
+,0xBF8C
+,0xA410
+,0x2A42
+,0xBC23
+,0x03C4
+,0x88D0
+,0x6D26
+,0xA19E
+,0xBC27
+,0x03C7
+,0x6E62
+,0xE15A
+,0x6E7A
+,0x5FC2
+,0x6E72
+,0x21DC
+,0x88A0
+,0x6D4E
+,0xA38E
+,0xA206
+,0x03A5
+,0xA300
+,0x03A6
+,0x6998
+,0x23CF
+,0xE24C
+,0xDFE5
+,0x8F03
+,0x8E00
+,0x8C16
+,0xB06C
+,0xFFFF
+,0x88E0
+,0x39FC
+,0x39DE
+,0x399A
+,0x8880
+,0xBC21
+,0x2045
+,0x2442
+,0x7007
+,0xBB30
+,0xBC20
+,0x2046
+,0xBC21
+,0x305A
+,0x7009
+,0xBB16
+,0x7007
+,0x3A30
+,0x3B4C
+,0x15B0
+,0x240A
+,0x4020
+,0x28C8
+,0xBC21
+,0x03BF
+,0xE7CF
+,0xA30E
+,0x03C7
+,0xBCAA
+,0x8000
+,0xA306
+,0x03A5
+,0x690B
+,0x60C6
+,0x6E20
+,0x664C
+,0x6E7F
+,0x2482
+,0x6E77
+,0xA0C7
+,0x6E66
+,0xA4C6
+,0x6A3A
+,0x0FC1
+,0xBC20
+,0x3068
+,0x6915
+,0x24CC
+,0xA30E
+,0x03C4
+,0x6915
+,0xE5CF
+,0x6915
+,0xBA01
+,0x6A34
+,0x7A02
+,0x6A3C
+,0xBA02
+,0xBC40
+,0x1205
+,0x6A3E
+,0xBA02
+,0x6A3A
+,0xBA16
+,0xBC40
+,0x1A03
+,0x6A3A
+,0x8FE0
+,0x28DE
+,0x88A0
+,0xBC40
+,0x1E05
+,0xBC40
+,0x1602
+,0xBC23
+,0x28BE
+,0xA204
+,0x03C3
+,0xBCA4
+,0xC000
+,0xB038
+,0x4000
+,0x009A
+,0xA302
+,0x03C3
+,0xBC23
+,0x3244
+,0xBCA4
+,0xC000
+,0xBC23
+,0x2111
+,0x8EC0
+,0xE9FE
+,0xFB72
+,0xA200
+,0x0398
+,0x2457
+,0xBC22
+,0x306D
+,0x77FE
+,0xA441
+,0xBC3C
+,0x0399
+,0x7067
+,0xBA43
+,0x6E73
+,0xE800
+,0x6915
+,0x3C1C
+,0x8A0A
+,0xBB8C
+,0x861C
+,0xBB8C
+,0xA413
+,0x28DA
+,0xA300
+,0x0398
+,0x8EC0
+,0x8880
+,0x8E00
+,0xE902
+,0xA203
+,0x0372
+,0x6CAC
+,0x1FD5
+,0x8F06
+,0xBC20
+,0x036A
+,0xBC21
+,0x213E
+,0xBC0B
+,0x15CB
+,0xFA32
+,0xE402
+,0xBC02
+,0x1445
+,0xBC02
+,0x148A
+,0xA201
+,0x0372
+,0x41E3
+,0xA202
+,0x0373
+,0x0459
+,0x2621
+,0xA301
+,0x0372
+,0x8F07
+,0x26A2
+,0x8F1A
+,0xA200
+,0x0374
+,0xBC02
+,0x1AEC
+,0x4002
+,0x8D16
+,0x3820
+,0xBC02
+,0x14AE
+,0x3820
+,0xBC02
+,0x1504
+,0xA201
+,0x03B8
+,0x2610
+,0x8F04
+,0xB002
+,0xFFFF
+,0x4002
+,0x8C08
+,0xA300
+,0x03B8
+,0x3820
+,0xBC02
+,0x15A4
+,0xA300
+,0x0374
+,0x4042
+,0xCFD5
+,0x8E00
+,0x8EC0
+,0xE9FE
+,0xA302
+,0x0373
+,0x3E02
+,0xBC20
+,0x03E5
+,0x3820
+,0xE002
+,0xE003
+,0xE044
+,0xE402
+,0xE484
+,0xE042
+,0xE482
+,0x7008
+,0xA443
+,0xA200
+,0x03E4
+,0x0C10
+,0xA300
+,0x03E4
+,0x3E01
+,0x8EB8
+,0xBC20
+,0x30BF
+,0xA201
+,0x0447
+,0xFA10
+,0x6852
+,0x2902
+,0xBC22
+,0x30BB
+,0xBC23
+,0x30BD
+,0x18D3
+,0xA202
+,0x0449
+,0xFA64
+,0x3491
+,0x6835
+,0x3A73
+,0x8F65
+,0xA202
+,0x0448
+,0x2153
+,0x8F07
+,0x3449
+,0x3401
+,0xA080
+,0x4000
+,0x4002
+,0x8C5B
+,0xA300
+,0x0447
+,0xBC20
+,0x30C1
+,0xA201
+,0x03CF
+,0xBC22
+,0x30BA
+,0x6114
+,0x5FF5
+,0x701F
+,0x3A10
+,0x4023
+,0x6220
+,0xDFDC
+,0xB412
+,0x0001
+,0x2620
+,0x8F04
+,0x7000
+,0x5FC1
+,0xA301
+,0x03CB
+,0xA301
+,0x03CC
+,0xBC22
+,0x30C0
+,0xA201
+,0x03D6
+,0x3449
+,0xFA52
+,0x20CA
+,0xA301
+,0x03D6
+,0x8F19
+,0x4041
+,0x0801
+,0x2600
+,0x8F13
+,0x3E02
+,0x4000
+,0xA300
+,0x0099
+,0x3E01
+,0xBC20
+,0x2008
+,0xBC21
+,0xFF7F
+,0xFA12
+,0x0851
+,0x7008
+,0x3B11
+,0xBC02
+,0x05B3
+,0x7010
+,0x4FC0
+,0x8C05
+,0xA301
+,0x009A
+,0x8C02
+,0x4060
+,0xCFC0
+,0x3302
+,0x8F18
+,0x3541
+,0xBC21
+,0x1111
+,0x2829
+,0x3200
+,0x380E
+,0x8F0D
+,0x70F0
+,0x4FF5
+,0xBC22
+,0x2042
+,0xBC23
+,0x2041
+,0xBC24
+,0xEEEF
+,0xBC0D
+,0x1681
+,0xFB51
+,0x6008
+,0x3B70
+,0x8C06
+,0x4002
+,0x8C04
+,0x7000
+,0x8FF5
+,0x7000
+,0x8FF5
+,0xA302
+,0x0448
+,0x8EC0
+,0xE9FE
+,0xA302
+,0x0449
+,0xA200
+,0x03CE
+,0xB300
+,0x6600
+,0x4020
+,0x3820
+,0x8F00
+,0xA200
+,0x044A
+,0x2681
+,0xA300
+,0x044A
+,0x8F27
+,0xA200
+,0x03D2
+,0x2600
+,0xBC22
+,0x2044
+,0x4000
+,0x1801
+,0xFA53
+,0x0118
+,0xBC23
+,0x2043
+,0xFB54
+,0xFA72
+,0x0448
+,0x0091
+,0xA204
+,0x03D5
+,0xFB72
+,0xB5C8
+,0x0001
+,0x0061
+,0xA202
+,0x044C
+,0x004A
+,0xBC23
+,0x2042
+,0xA204
+,0x0448
+,0xA300
+,0x03D2
+,0xBC22
+,0x2041
+,0xA205
+,0x03CA
+,0x0020
+,0xFB71
+,0xA300
+,0x0448
+,0xFB55
+,0xBC00
+,0x1612
+,0x8EB8
+,0xA201
+,0x03D5
+,0x3312
+,0xA201
+,0x03CE
+,0x8F0A
+,0xB312
+,0x3F00
+,0x8F07
+,0xA202
+,0x03D4
+,0x224A
+,0x8F04
+,0x4001
+,0x7008
+,0x2441
+,0xA300
+,0x03D0
+,0x8EB8
+,0x2680
+,0xA200
+,0x03CF
+,0x8F0A
+,0xFA11
+,0xB312
+,0x0198
+,0x8F05
+,0xA201
+,0x03D3
+,0x1641
+,0x40A2
+,0x2E4A
+,0x8F00
+,0x3401
+,0x3402
+,0xBC21
+,0x30BB
+,0x2041
+,0x8F04
+,0x4000
+,0xA300
+,0x03D0
+,0xBC20
+,0x30B3
+,0xA201
+,0x03D0
+,0x2611
+,0x4001
+,0x8F00
+,0xFA11
+,0xA300
+,0x03CF
+,0x8EC0
+,0xB592
+,0x0006
+,0xA301
+,0x03CE
+,0x6EF5
+,0x6080
+,0xE906
+,0x7007
+,0x20C1
+,0xA204
+,0x03CE
+,0x6313
+,0x1F83
+,0x65B0
+,0x5FA2
+,0x65C0
+,0x1FE3
+,0x7000
+,0x9FC0
+,0x4020
+,0x4207
+,0x5FE6
+,0xBC23
+,0xC6C0
+,0xBC21
+,0x6E40
+,0x38A2
+,0xBC0F
+,0x1720
+,0x2F68
+,0x2F20
+,0x8F00
+,0x0D6B
+,0x2FB0
+,0x8F00
+,0x0D69
+,0x1785
+,0x3491
+,0x4044
+,0x6815
+,0x0FE4
+,0x4147
+,0x8FEE
+,0x6E1D
+,0x0FA2
+,0xB036
+,0xFFFB
+,0x69A8
+,0x5FE3
+,0x8F08
+,0xB42A
+,0x0006
+,0xBC23
+,0x03FF
+,0x0893
+,0xA31C
+,0x03D5
+,0xDF62
+,0xA302
+,0x03D2
+,0x7000
+,0x8F83
+,0xBC21
+,0x7F80
+,0x3882
+,0xBD10
+,0x174F
+,0x2E90
+,0x2F68
+,0x2FB0
+,0x8F0B
+,0x26B1
+,0x8F02
+,0x09E9
+,0x2670
+,0x8F03
+,0xBC26
+,0x6E40
+,0x0D6E
+,0x8C03
+,0x1785
+,0x3521
+,0x3491
+,0x8E00
+,0xCFA0
+,0x2601
+,0xBC20
+,0x03FF
+,0x8F27
+,0xB41A
+,0x0006
+,0x0808
+,0x2680
+,0x8F01
+,0x32C2
+,0x8F00
+,0x403C
+,0x26B0
+,0xDF7C
+,0x8F12
+,0xBC22
+,0x30B3
+,0x6E20
+,0x8FC3
+,0xBC21
+,0x30BB
+,0xBD04
+,0x1772
+,0xFA86
+,0x6881
+,0xBA86
+,0x8F01
+,0x2246
+,0x8F03
+,0x21E1
+,0x1914
+,0xA304
+,0x03CF
+,0x8E00
+,0x8D0B
+,0xCFC0
+,0x6330
+,0x8FE0
+,0xA305
+,0x03D4
+,0xA304
+,0x03D5
+,0xBC02
+,0x16C7
+,0x8D01
+,0xCFC3
+,0x6EAF
+,0x8F60
+,0xA303
+,0x03D3
+,0x8EC0
+,0xE9FA
+,0xA305
+,0x03D4
+,0xB022
+,0x3098
+,0xA200
+,0x03D2
+,0x6980
+,0x3A45
+,0x8F26
+,0x4343
+,0x0519
+,0x4003
+,0xBC0C
+,0x1799
+,0xFA46
+,0x0DAE
+,0x2246
+,0x8F01
+,0x3882
+,0x3803
+,0x8E00
+,0x2680
+,0x8F18
+,0x2610
+,0x4046
+,0x4022
+,0x1996
+,0x4205
+,0x3290
+,0x0569
+,0xA306
+,0x03D5
+,0x8F02
+,0x3250
+,0x8F00
+,0x14D5
+,0xBC21
+,0x30A9
+,0x044C
+,0x3210
+,0x8F01
+,0x1451
+,0x00D9
+,0xA201
+,0x03D3
+,0x0C4B
+,0xA301
+,0x03D3
+,0x8EC0
+,0xA300
+,0x03D2
+,0x8E00
+,0xE904
+,0xA201
+,0x03CC
+,0xA200
+,0x03CD
+,0x7000
+,0x9F81
+,0xB000
+,0xFFFF
+,0xA302
+,0x03CE
+,0x6984
+,0x1FB5
+,0x8F4C
+,0x2680
+,0x8F47
+,0xA201
+,0x03CF
+,0x344A
+,0xBC20
+,0x30BB
+,0x21C8
+,0xBC20
+,0x30B3
+,0x1841
+,0x6E18
+,0x9FC1
+,0xBC21
+,0x03D7
+,0xBC02
+,0x1700
+,0xA201
+,0x03CF
+,0x7000
+,0x8FC0
+,0xA204
+,0x0444
+,0x6882
+,0x1FC1
+,0x4023
+,0x8F06
+,0xB018
+,0xFFFF
+,0x6CC7
+,0x9FC0
+,0x6626
+,0x9FE1
+,0x8C20
+,0xDF82
+,0x3422
+,0x6CE1
+,0x1FE0
+,0x181A
+,0x2681
+,0xA300
+,0x03CB
+,0x8F15
+,0xBC20
+,0x0444
+,0x8A09
+,0xE402
+,0xFA31
+,0xA21E
+,0x03D3
+,0xB592
+,0x0006
+,0xA302
+,0x03D0
+,0xA303
+,0x03D1
+,0xA302
+,0x03D5
+,0xA302
+,0x03D2
+,0xA301
+,0x03CE
+,0xA31E
+,0x03CA
+,0xBC02
+,0x1690
+,0xCFE2
+,0xCFC1
+,0xA302
+,0x0444
+,0xA301
+,0x03CF
+,0x8C26
+,0x71A0
+,0x0F85
+,0x8C23
+,0xCF85
+,0x2600
+,0x4681
+,0x1848
+,0x7008
+,0x1FC1
+,0x2C48
+,0x401E
+,0xBC21
+,0x03D9
+,0xBC20
+,0x03D7
+,0xA31E
+,0x03CF
+,0x1848
+,0x3862
+,0xBC02
+,0x1700
+,0xA202
+,0x03CF
+,0x6988
+,0x0FC0
+,0x4025
+,0x8F09
+,0x0885
+,0x2620
+,0x4006
+,0x8F00
+,0xBC02
+,0x15FE
+,0xA306
+,0x0444
+,0x8C02
+,0x4680
+,0xCF85
+,0xCFB5
+,0xA305
+,0x03CC
+,0x8EC0
+,0xE9FC
+,0xA300
+,0x03CD
+,0xE902
+,0xA203
+,0x03CD
+,0xB036
+,0xFFFF
+,0x698C
+,0x1FC3
+,0xDFF5
+,0xBC01
+,0x190F
+,0xA201
+,0x03D1
+,0x2690
+,0xBC01
+,0x1920
+,0xB016
+,0xFFE6
+,0x4340
+,0x2048
+,0xBC01
+,0x190A
+,0xB306
+,0x0019
+,0xBC01
+,0x18F4
+,0xA201
+,0x03D2
+,0xB306
+,0x0018
+,0x8F7E
+,0xB306
+,0x0017
+,0x8F4E
+,0xCFC3
+,0xB316
+,0x0016
+,0xBC01
+,0x1920
+,0xA203
+,0x044B
+,0x26B0
+,0xBC01
+,0x1920
+,0x4023
+,0x2610
+,0xA303
+,0x044B
+,0x4002
+,0x8F0F
+,0xBC21
+,0x03D7
+,0xBC02
+,0x1700
+,0x2680
+,0xA300
+,0x03D2
+,0x8F07
+,0xA203
+,0x0444
+,0xA21E
+,0x03D3
+,0x34D9
+,0xA31E
+,0x03CA
+,0xA303
+,0x0444
+,0xA203
+,0x0444
+,0xB236
+,0x0080
+,0x8F19
+,0xA203
+,0x0446
+,0xB236
+,0x0080
+,0x7000
+,0xCFC5
+,0xBC21
+,0x0444
+,0x8F09
+,0xA200
+,0x0445
+,0xB200
+,0x0080
+,0x8F12
+,0x8A03
+,0xE483
+,0x3569
+,0xBC02
+,0x15FE
+,0x8D0D
+,0x8A03
+,0xE483
+,0xB05A
+,0xFFFF
+,0xBC02
+,0x15FE
+,0x8D06
+,0x7000
+,0xCFC5
+,0xBC21
+,0x0444
+,0x8A03
+,0xE483
+,0xA200
+,0x03D2
+,0xDFC5
+,0xBC02
+,0x16DA
+,0xBC02
+,0x1690
+,0x8D73
+,0x2610
+,0xBC21
+,0x03D7
+,0x8F24
+,0xBC40
+,0x1880
+,0x4023
+,0x2E03
+,0xBC40
+,0x1C80
+,0x4002
+,0x185A
+,0xA200
+,0x03D9
+,0x2E03
+,0x0001
+,0xA300
+,0x03D9
+,0xBC21
+,0x03D9
+,0x441A
+,0xBC02
+,0x1700
+,0x2680
+,0xA300
+,0x03D2
+,0x8F0B
+,0xA203
+,0x0445
+,0xA201
+,0x03D3
+,0x34D9
+,0xA301
+,0x03CA
+,0xA31A
+,0x044C
+,0xA303
+,0x0445
+,0x8C04
+,0x4003
+,0x8C02
+,0x4003
+,0x4003
+,0x8C47
+,0xA303
+,0x044B
+,0x2610
+,0xBC21
+,0x03D9
+,0x4002
+,0x4023
+,0x8F3D
+,0xBC02
+,0x1700
+,0x2680
+,0xA300
+,0x03D2
+,0x8F37
+,0xA203
+,0x0446
+,0x441E
+,0xA201
+,0x03D3
+,0x34D9
+,0xA301
+,0x03CA
+,0xA31E
+,0x044C
+,0xA303
+,0x0446
+,0x8D2C
+,0xA203
+,0x03D4
+,0x2630
+,0xBC20
+,0x03D2
+,0x8F00
+,0xBC02
+,0x16C7
+,0xA203
+,0x03D2
+,0x26B0
+,0x8F1E
+,0xA203
+,0x0444
+,0xA21E
+,0x03D3
+,0x34D9
+,0xA31E
+,0x03CA
+,0xA303
+,0x0444
+,0x8D16
+,0x4661
+,0x044B
+,0xBC02
+,0x1787
+,0x8D11
+,0xA200
+,0x03D7
+,0x4010
+,0x4023
+,0xA300
+,0x03CA
+,0xA310
+,0x03D1
+,0xBC21
+,0x03D7
+,0x3843
+,0xBC02
+,0x1700
+,0x4683
+,0xA310
+,0x044C
+,0xDFC3
+,0xCFF5
+,0xCFC3
+,0x8EC0
+,0xE9FE
+,0xA303
+,0x03CD
+,0xE902
+,0x8E00
+,0xDFD5
+,0x3E02
+,0xA200
+,0x03E3
+,0x7000
+,0x5FE0
+,0xA301
+,0x03E3
+,0x2600
+,0x8F12
+,0xA200
+,0x03CB
+,0x2680
+,0x8F02
+,0xA200
+,0x03CC
+,0x2600
+,0x8F02
+,0xA200
+,0x03CD
+,0x2681
+,0x8F06
+,0xBC20
+,0x03E5
+,0xBC21
+,0x03D7
+,0xBD04
+,0x1945
+,0xE002
+,0xE482
+,0x3E01
+,0x8C0E
+,0xCFE0
+,0xA200
+,0x03CB
+,0x2601
+,0x8F02
+,0xBC02
+,0x17B9
+,0x8C04
+,0xCFE0
+,0xBC02
+,0x183D
+,0xCFE0
+,0xB000
+,0xFFFF
+,0x69A0
+,0x1FE0
+,0x8FEF
+,0xCFD5
+,0x8E00
+,0x8EC0
+,0xE9FE
+,0x8E00
+,0xBC20
+,0x2048
+,0x8E00
+,0xFA10
+,0x2600
+,0x8F06
+,0xBC20
+,0x2043
+,0xBC22
+,0x2044
+,0x4001
+,0x8EC0
+,0xFB11
+,0xFB51
+,0x8EB8
+,0xA201
+,0x03E1
+,0xBC22
+,0x3079
+,0xFA20
+,0xB030
+,0xFFD8
+,0xB302
+,0x308C
+,0xA303
+,0x03EE
+,0x8EC0
+,0x1851
+,0xA301
+,0x03E1
+,0xA203
+,0x03E3
+,0x34D9
+,0xA200
+,0x03FD
+,0x5FFA
+,0xBC3C
+,0x03FA
+,0x407E
+,0xA303
+,0x03E3
+,0x7009
+,0x2461
+,0x6CE4
+,0x3C1E
+,0x4003
+,0xA205
+,0x03E4
+,0x19E3
+,0x0C95
+,0x2131
+,0x6555
+,0x2042
+,0x1863
+,0xA300
+,0x03FD
+,0x33A0
+,0xB05A
+,0x03E6
+,0x1823
+,0x637E
+,0x22C0
+,0x2E04
+,0xB5FE
+,0x0005
+,0x01C7
+,0x6678
+,0xE6A7
+,0x684C
+,0xA2C2
+,0x18E3
+,0x0C0B
+,0x2E94
+,0x8EC0
+,0x0097
+,0xE6C2
+,0xA200
+,0x03DB
+,0xBC3C
+,0x03DC
+,0x409E
+,0x405A
+,0xBC22
+,0x03EA
+,0x77FE
+,0xAA18
+,0xE05F
+,0xBC23
+,0x308C
+,0xE51F
+,0xBD03
+,0x19C3
+,0x6910
+,0xBC1C
+,0xFA65
+,0x8A03
+,0xBBB0
+,0xCA1C
+,0x28EC
+,0x88C0
+,0x8E00
+,0xE504
+,0x8EC0
+,0xEA18
+,0xA300
+,0x03DB
+,0xBC26
+,0x03E2
+,0xA202
+,0x03E9
+,0xE343
+,0x698C
+,0x2902
+,0xA203
+,0x03E0
+,0xBC01
+,0x1A6F
+,0xA204
+,0x03F6
+,0x69B0
+,0x5FD5
+,0x3883
+,0x8F02
+,0x4004
+,0xA304
+,0x03F6
+,0x3342
+,0x8F68
+,0xBC26
+,0x03F7
+,0x602D
+,0x215F
+,0x26C0
+,0xE55F
+,0x8F61
+,0x6E11
+,0xBCC5
+,0x6CF4
+,0x2341
+,0x4004
+,0x4026
+,0x19B4
+,0x3210
+,0x8F00
+,0x35B1
+,0xBC40
+,0x1102
+,0x3220
+,0x8F00
+,0x35B1
+,0x2663
+,0xA207
+,0x03F1
+,0x8F01
+,0x26E0
+,0x8F09
+,0x2435
+,0x2429
+,0x2412
+,0x20B5
+,0x8F00
+,0x35F9
+,0x2095
+,0x8F00
+,0xB07E
+,0xFFFF
+,0xA202
+,0x03F2
+,0x3551
+,0xB20A
+,0x004C
+,0x3844
+,0x8F0B
+,0xB23E
+,0x0008
+,0x38A7
+,0x4024
+,0x38E2
+,0x8F05
+,0x38E5
+,0x3378
+,0x3882
+,0x8F01
+,0x5FE4
+,0x38E2
+,0x38A2
+,0x00E3
+,0xA305
+,0x03F2
+,0xA307
+,0x03F1
+,0xDFE3
+,0xBC02
+,0x197C
+,0xA203
+,0x03F5
+,0xA202
+,0x03F3
+,0x6056
+,0x0FE4
+,0x3491
+,0xB438
+,0x0001
+,0xA305
+,0x03F5
+,0xB204
+,0x0208
+,0x8F14
+,0xA202
+,0x03F5
+,0xA205
+,0x03F4
+,0xB524
+,0x0001
+,0x20AA
+,0x401D
+,0x8F06
+,0xA202
+,0x03E4
+,0x4024
+,0x0C94
+,0x3883
+,0xA302
+,0x03E4
+,0x4643
+,0xA31D
+,0x03F5
+,0xA31D
+,0x03F4
+,0x4002
+,0xA303
+,0x03EF
+,0xA302
+,0x03F3
+,0xA202
+,0x03EF
+,0x2222
+,0x8F09
+,0x3491
+,0x2262
+,0x8F11
+,0xA202
+,0x03E9
+,0x8E00
+,0xE142
+,0xA302
+,0x03F0
+,0x8D0C
+,0xA201
+,0x03F0
+,0x7008
+,0x9FE4
+,0xBC02
+,0x197C
+,0xA202
+,0x03F4
+,0x6024
+,0x0FE4
+,0xA302
+,0x03F4
+,0xB008
+,0xFFFF
+,0x69A0
+,0x0FD5
+,0x8F79
+,0x700F
+,0xDFD5
+,0xBC02
+,0x196D
+,0xA31F
+,0x03F6
+,0xCFD5
+,0x8D73
+,0x7766
+,0xE145
+,0xA202
+,0x03F0
+,0x3822
+,0xBC3D
+,0x03F1
+,0x453F
+,0xA204
+,0x0442
+,0x69AC
+,0x64E5
+,0x6E28
+,0x6A38
+,0x8F02
+,0xA207
+,0x03EE
+,0x26F0
+,0x8F15
+,0xE142
+,0xE2C5
+,0x6175
+,0x60C2
+,0x615A
+,0xA242
+,0x243F
+,0x242D
+,0x017D
+,0xB05A
+,0x0008
+,0xB4DA
+,0x0004
+,0x356A
+,0xB4DA
+,0x0002
+,0x016A
+,0x206A
+,0x5FE2
+,0x1955
+,0x8C02
+,0xE605
+,0x5FE2
+,0xB006
+,0xFFFF
+,0x2680
+,0x8F3F
+,0xA203
+,0x0443
+,0x34D9
+,0xA303
+,0x0443
+,0xB236
+,0x00F0
+,0x8F08
+,0xDFC1
+,0xDFF5
+,0xBC24
+,0x041A
+,0xBC02
+,0x196D
+,0xCFF5
+,0x8C31
+,0xCFC1
+,0xBC24
+,0x041A
+,0x4003
+,0x6E38
+,0xE200
+,0x4005
+,0xA071
+,0xC000
+,0xBD27
+,0x1ABA
+,0x6659
+,0x6200
+,0xA071
+,0xC000
+,0x1965
+,0xA207
+,0x03EE
+,0xB0DA
+,0x041A
+,0x003D
+,0xB450
+,0x0001
+,0xA305
+,0x03EF
+,0x26D0
+,0x4685
+,0x4667
+,0x405F
+,0x19EF
+,0xE71F
+,0xA307
+,0x03CD
+,0xBC25
+,0x03F0
+,0x8A06
+,0xE703
+,0x8A0A
+,0xE683
+,0x8A03
+,0xE682
+,0xBC3F
+,0x03FA
+,0xA303
+,0x03CC
+,0xA31F
+,0x03FD
+,0xA303
+,0x03CB
+,0xA304
+,0x0442
+,0xA301
+,0x03F0
+,0xE9FE
+,0xA300
+,0x03E0
+,0xA202
+,0x03E9
+,0x8EC0
+,0x3491
+,0xA302
+,0x03E9
+,0x0000
+,0xE902
+,0xA201
+,0x03DB
+,0xDFD5
+,0x6960
+,0x24C0
+,0xBC02
+,0x19AA
+,0xBC20
+,0x03EA
+,0xA300
+,0x03E9
+,0xBD04
+,0x1AFD
+,0xBC02
+,0x19C8
+,0x8E00
+,0x8E00
+,0xCFD5
+,0x8E00
+,0x8EC0
+,0xE9FE
+,0x8E00
+,0xE902
+,0xA200
+,0x0466
+,0x6980
+,0x1FC0
+,0xBC01
+,0x1BB4
+,0xB310
+,0x00FF
+,0xBC01
+,0x1BBA
+,0xA201
+,0x0468
+,0xA202
+,0x0467
+,0xB034
+,0xFFFF
+,0x3310
+,0xBC20
+,0x0450
+,0xBC01
+,0x1BAA
+,0x3880
+,0x4021
+,0xE20E
+,0xE24F
+,0xBC24
+,0x3002
+,0x88D8
+,0xFA94
+,0xBCDB
+,0x0000
+,0xBC24
+,0x3009
+,0x2435
+,0xFA94
+,0x2134
+,0x4004
+,0x19CC
+,0xA307
+,0x0465
+,0xBC27
+,0x3013
+,0xA305
+,0x0464
+,0xFAF7
+,0x21B7
+,0x198C
+,0x26E0
+,0x8F04
+,0xBC26
+,0x2004
+,0x8E00
+,0xFAD6
+,0x2660
+,0x8F03
+,0xA206
+,0x046A
+,0x35B1
+,0xA306
+,0x046A
+,0xBC27
+,0x3011
+,0xA206
+,0x0469
+,0x35B1
+,0xFAF7
+,0x2037
+,0xA306
+,0x0469
+,0x8F0F
+,0xBC26
+,0x3012
+,0xA207
+,0x046A
+,0xFAD6
+,0x21BE
+,0x8F03
+,0x8E00
+,0x8C04
+,0xA304
+,0x046B
+,0xA301
+,0x046B
+,0xA304
+,0x046A
+,0xA304
+,0x0469
+,0xBC26
+,0x300A
+,0x8E00
+,0xFAD6
+,0x212E
+,0x0526
+,0x19B5
+,0x202C
+,0xBC25
+,0x2017
+,0x1926
+,0x6CA8
+,0x3AB2
+,0xBC25
+,0x3006
+,0x8F02
+,0xA303
+,0x0467
+,0xBC25
+,0x3003
+,0xBC23
+,0x300C
+,0x8E00
+,0xFA73
+,0x2013
+,0x8F13
+,0xBC26
+,0x300D
+,0x34E9
+,0xFAD6
+,0x2016
+,0x8F0C
+,0xBC26
+,0x300E
+,0x8E00
+,0xFAD6
+,0x2016
+,0x8F05
+,0xBC26
+,0x300F
+,0x8E00
+,0xFAD6
+,0x2016
+,0x8C02
+,0x18DD
+,0x34EA
+,0x38A3
+,0x2442
+,0xFAB2
+,0x28E2
+,0x88A0
+,0xBC23
+,0x300B
+,0xB524
+,0x0006
+,0xFA73
+,0xB424
+,0x0006
+,0x32B0
+,0x8F01
+,0x4003
+,0x049A
+,0xBC23
+,0x2020
+,0xB524
+,0x0001
+,0xFA73
+,0x0859
+,0x2690
+,0xBC23
+,0x2003
+,0x8F02
+,0x4001
+,0x8C0C
+,0xFB71
+,0x3451
+,0x8C09
+,0x7000
+,0x7B71
+,0xB012
+,0xFFFF
+,0xA301
+,0x0468
+,0xA303
+,0x0467
+,0x4001
+,0xE401
+,0xE441
+,0x8D06
+,0xBC20
+,0x2003
+,0x5FC1
+,0xFA12
+,0x0851
+,0xFB11
+,0xCFC0
+,0x3401
+,0xE9FE
+,0xBC21
+,0x00FF
+,0x8EC0
+,0x0801
+,0xA300
+,0x0466
+,0xE904
+,0xBC21
+,0x2016
+,0x6E05
+,0x1FD5
+,0xB000
+,0xFFFD
+,0xBC22
+,0x3000
+,0xFA31
+,0x7000
+,0x6441
+,0xFA52
+,0xBC23
+,0x044D
+,0xBC24
+,0x044F
+,0xBC02
+,0x1E36
+,0xA200
+,0x044F
+,0x7003
+,0x0FD5
+,0xBC22
+,0x4444
+,0x6915
+,0xE9FC
+,0x2456
+,0x28C2
+,0xBC20
+,0x3001
+,0x8890
+,0xBC22
+,0x0450
+,0x6910
+,0xBA10
+,0x28C8
+,0x6E00
+,0xBC41
+,0x88B4
+,0x7101
+,0x2145
+,0x24A9
+,0x28DC
+,0x2444
+,0x8EC0
+,0xE54F
+,0xE44E
+,0xBC21
+,0x3033
+,0xBC22
+,0x201E
+,0xB580
+,0x0001
+,0xFA31
+,0x4043
+,0xFA54
+,0x0923
+,0xB012
+,0xFFFF
+,0x2220
+,0x8F01
+,0x3310
+,0x8FF7
+,0x8EB8
+,0xA200
+,0x0470
+,0x3280
+,0xBC21
+,0x0477
+,0xBC22
+,0x0474
+,0x184A
+,0xA202
+,0x046D
+,0xBC40
+,0x1083
+,0x6CE8
+,0xE084
+,0x66B7
+,0x20C1
+,0x8F04
+,0xB044
+,0x3014
+,0x8E00
+,0xFA94
+,0x211C
+,0x8F0B
+,0x32A0
+,0xB044
+,0xFFFF
+,0x8F07
+,0xB058
+,0x3017
+,0x8E00
+,0xFAB5
+,0x219D
+,0x8F02
+,0x3844
+,0x8D01
+,0x3491
+,0xB034
+,0x301A
+,0xA302
+,0x046D
+,0xFA73
+,0xBC22
+,0x3023
+,0x1A59
+,0x2419
+,0xFA52
+,0x211A
+,0x8F05
+,0x3300
+,0x8F02
+,0xBC20
+,0x301F
+,0x8C05
+,0xFA10
+,0xBC20
+,0x301E
+,0x8E00
+,0xFA10
+,0x4202
+,0x0490
+,0xA203
+,0x0473
+,0x2442
+,0x28DA
+,0x28C8
+,0x8884
+,0xBC21
+,0x0200
+,0xBC90
+,0x4000
+,0xBC22
+,0x0800
+,0xBC80
+,0x8000
+,0xBC22
+,0x3024
+,0x2690
+,0x4004
+,0xA203
+,0x0454
+,0x1820
+,0xFA52
+,0x0E4B
+,0x210A
+,0xA300
+,0x0473
+,0x8F04
+,0xBC20
+,0x3025
+,0x8E00
+,0xFA10
+,0x2008
+,0x1881
+,0x8EC0
+,0xA302
+,0x0454
+,0x8E00
+,0xBC20
+,0x200F
+,0xA201
+,0x046E
+,0xFA10
+,0x2680
+,0x8F00
+,0x3449
+,0x2682
+,0x4000
+,0x8F00
+,0xB012
+,0xFFFF
+,0x3210
+,0x8F02
+,0x3317
+,0x40E0
+,0x1801
+,0x8EC0
+,0xA300
+,0x046E
+,0x8E00
+,0xBC20
+,0x3031
+,0xBC21
+,0x2000
+,0xFA12
+,0x0811
+,0x2241
+,0xA200
+,0x046E
+,0x8F03
+,0x4E00
+,0x0810
+,0xB400
+,0x0004
+,0xB010
+,0x3026
+,0xA203
+,0x0454
+,0xFA31
+,0xBC24
+,0x1000
+,0x0994
+,0x1AD9
+,0x2274
+,0x34D9
+,0x4025
+,0x111D
+,0x8F01
+,0x41E3
+,0x0913
+,0x4002
+,0x3240
+,0x3862
+,0x8F02
+,0x4103
+,0x2123
+,0x18DC
+,0xB5C6
+,0x0001
+,0xBC26
+,0x302E
+,0x0E4C
+,0x6980
+,0x3AD6
+,0xBC24
+,0x200B
+,0xB5F0
+,0x0004
+,0xA303
+,0x046F
+,0x1895
+,0x0E4E
+,0xA300
+,0x046E
+,0x00FB
+,0x6988
+,0x3B91
+,0x8F01
+,0x2681
+,0x8F00
+,0x4002
+,0x2620
+,0x8F01
+,0x2682
+,0x8F00
+,0x4002
+,0x2620
+,0x8F01
+,0x2683
+,0x8F00
+,0x4002
+,0x2620
+,0x8F40
+,0x2604
+,0x8F3E
+,0x2620
+,0x8F01
+,0x2685
+,0x8F00
+,0x4002
+,0x2620
+,0x8F33
+,0x2606
+,0x8F31
+,0x2620
+,0x8F01
+,0x2687
+,0x8F33
+,0xBC20
+,0x2005
+,0xBC21
+,0x0200
+,0xFA10
+,0x0801
+,0x2680
+,0x8F20
+,0xA200
+,0x0452
+,0x2602
+,0x8F11
+,0x2603
+,0x8F03
+,0x4060
+,0x8C25
+,0xA300
+,0x0452
+,0xBC20
+,0x3036
+,0xBC21
+,0x2081
+,0xFA10
+,0xFA31
+,0x2088
+,0x4040
+,0x8F18
+,0xA300
+,0x0452
+,0x8D17
+,0xBC20
+,0x3037
+,0xBC21
+,0x2081
+,0xFA10
+,0xFA31
+,0x2188
+,0x4060
+,0x8F0C
+,0xA300
+,0x0452
+,0x8D0B
+,0x4060
+,0xA300
+,0x0452
+,0x8D07
+,0x4020
+,0x8C05
+,0xA300
+,0x0452
+,0x4000
+,0xA300
+,0x0452
+,0xA200
+,0x0452
+,0xB000
+,0x3039
+,0xBC21
+,0x2006
+,0xFA10
+,0x8EC0
+,0x0003
+,0xFB30
+,0xA200
+,0x0474
+,0xA201
+,0x0453
+,0xB500
+,0x0007
+,0xBC22
+,0x302F
+,0x1AC8
+,0x241B
+,0xFA52
+,0x211A
+,0x8F02
+,0xBC22
+,0x3021
+,0x8C05
+,0xFA52
+,0xBC22
+,0x3020
+,0x8E00
+,0xFA52
+,0xA204
+,0x046C
+,0xBC23
+,0x8000
+,0x04DA
+,0x3340
+,0x2457
+,0x2456
+,0x8F04
+,0x2454
+,0x28CB
+,0x28C2
+,0x8C03
+,0x8880
+,0xA30E
+,0x046C
+,0xBC21
+,0x3030
+,0xBC22
+,0x3032
+,0xA300
+,0x0453
+,0xFA31
+,0xFA52
+,0xBC23
+,0x1000
+,0x0913
+,0x1A08
+,0xBC25
+,0x0400
+,0x2263
+,0xBC81
+,0x4000
+,0x8F01
+,0xBC20
+,0x0FFF
+,0x0810
+,0xBC21
+,0x200C
+,0x8EC0
+,0x8E00
+,0xFB30
+,0x0000
+,0xBC20
+,0x3022
+,0xBC21
+,0x3038
+,0x7017
+,0xBA10
+,0x700C
+,0x3A31
+,0xA310
+,0x046C
+,0xA31E
+,0x0470
+,0xA300
+,0x0454
+,0xA301
+,0x0452
+,0x6EE5
+,0x6800
+,0xBD0F
+,0x1D81
+,0xBC20
+,0x3034
+,0xBC21
+,0x2005
+,0xFA10
+,0xB000
+,0x0301
+,0x7008
+,0x3B30
+,0xBC02
+,0x1BF3
+,0xBC02
+,0x1C65
+,0xBC02
+,0x1C7B
+,0xBC20
+,0x3034
+,0xBC21
+,0x2005
+,0xFA10
+,0xB000
+,0x0201
+,0x7000
+,0x3B30
+,0xBC02
+,0x1BF3
+,0x8E00
+,0x8E00
+,0xBC20
+,0x3034
+,0xBC21
+,0x2005
+,0xFA10
+,0xB000
+,0x0301
+,0x7008
+,0x3B30
+,0xBC02
+,0x1BF3
+,0xBC02
+,0x1C65
+,0xBC02
+,0x1C7B
+,0xA201
+,0x046E
+,0xBC20
+,0x3034
+,0xB012
+,0x3026
+,0x6EAF
+,0x3A10
+,0xBC22
+,0x3035
+,0xBC23
+,0x2005
+,0xFA31
+,0xB000
+,0x0201
+,0xFA52
+,0xA301
+,0x0454
+,0xFB70
+,0xBC24
+,0x2009
+,0x8EC0
+,0x7008
+,0x3B72
+,0xFB90
+,0xE902
+,0xA200
+,0x0470
+,0x6CC0
+,0x1FD5
+,0x8F34
+,0xA200
+,0x0472
+,0xA201
+,0x0471
+,0x2680
+,0x8F0F
+,0xB312
+,0x007F
+,0xBC20
+,0x3035
+,0x8F07
+,0xFA10
+,0xB000
+,0x0101
+,0xBC21
+,0x2005
+,0x8C03
+,0x7008
+,0x3B30
+,0x4020
+,0x8C1E
+,0xA300
+,0x0472
+,0xB232
+,0x007F
+,0x4000
+,0x8F00
+,0x3409
+,0x3300
+,0xA300
+,0x0471
+,0x8F0A
+,0xBC02
+,0x1C65
+,0xBC02
+,0x1C7B
+,0xBC20
+,0x3035
+,0xBC21
+,0x2005
+,0xFA10
+,0x8C07
+,0x7000
+,0x3B30
+,0xBC02
+,0x1C04
+,0xBC02
+,0x1C7B
+,0x4000
+,0xA300
+,0x0472
+,0xBC02
+,0x1D12
+,0x8D13
+,0xBC02
+,0x1C04
+,0xBC02
+,0x1C7B
+,0xA200
+,0x0470
+,0xB000
+,0xFFFF
+,0xA201
+,0x0471
+,0xA300
+,0x0470
+,0xB232
+,0x007F
+,0x4000
+,0x8F00
+,0x3409
+,0xA300
+,0x0471
+,0x7008
+,0x4FD5
+,0xBC20
+,0x2009
+,0x8EC0
+,0xE9FE
+,0xFB11
+,0xBC21
+,0x2010
+,0xE908
+,0xBC20
+,0x200E
+,0xFA31
+,0xFA12
+,0xBC24
+,0x7F00
+,0x6E1D
+,0x1F95
+,0xB036
+,0xFFF9
+,0x0894
+,0xB444
+,0x0008
+,0x6E10
+,0xE581
+,0xFA10
+,0x73F8
+,0x65C4
+,0x0801
+,0xBC21
+,0x0474
+,0xBC40
+,0x1500
+,0xDFA1
+,0xBD03
+,0x1E2E
+,0xE0DC
+,0xE101
+,0xDFC2
+,0xDFFC
+,0xBC02
+,0x1E46
+,0xCFE1
+,0x63A0
+,0x4FA1
+,0x6D34
+,0x4FC2
+,0x6E20
+,0x6480
+,0xB406
+,0x0001
+,0xBC40
+,0x1E00
+,0xDFA1
+,0x7000
+,0x0F95
+,0xBC21
+,0x2009
+,0x8EC0
+,0xE9F8
+,0xFB30
+,0xE040
+,0x6C00
+,0x6246
+,0x6E08
+,0xE185
+,0x6681
+,0xA1C6
+,0x24B5
+,0x28C2
+,0x2444
+,0x8E00
+,0xE5CF
+,0x88B8
+,0x8EC0
+,0xE4CE
+,0xE643
+,0x3291
+,0x8F0C
+,0x24C1
+,0x1448
+,0x41A2
+,0x2442
+,0x4403
+,0x0410
+,0x28CB
+,0xB580
+,0x0004
+,0x8890
+,0x8EC0
+,0x0001
+,0x8E00
+,0x8EC0
+,0x4000
+,0x8E00
+,0xBC20
+,0x2092
+,0x4041
+,0xFA10
+,0xBC22
+,0x2093
+,0x0841
+,0x6984
+,0xBA51
+,0x8F0F
+,0x4022
+,0x0802
+,0x2681
+,0x8F17
+,0xBC20
+,0x2000
+,0x21C8
+,0xBC20
+,0x2095
+,0x8F02
+,0x8EC0
+,0xE0C1
+,0xFB11
+,0xFA31
+,0xFB11
+,0x8EB8
+,0xBC20
+,0x2094
+,0xBC22
+,0x2000
+,0x6872
+,0xBA10
+,0x8F02
+,0x8EC0
+,0xE4C0
+,0x8E00
+,0x8EC0
+,0xFB30
+,0x8E00
+,0x8EB8
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+};
+#endif
+
+const unsigned short bin_patch_E1[] = { 
+0x2000
+,0x21FF
+,0xBC24
+,0x20A0
+,0x8E00
+,0xFA95
+,0xB30A
+,0x06AF
+,0x8F2E
+,0xB30A
+,0x08E5
+,0x8F07
+,0xBC25
+,0x08E5
+,0xFB95
+,0xBC22
+,0x399E
+,0xBC23
+,0x199E
+,0xBC00
+,0x0841
+,0xBC25
+,0x06AF
+,0xFB95
+,0x5400
+,0xBC21
+,0xD0B1
+,0xBC02
+,0x07CA
+,0x5500
+,0xBC21
+,0x07C2
+,0xBC02
+,0x07CA
+,0x40A0
+,0xBC21
+,0x0359
+,0xBC02
+,0x07CA
+,0x41A0
+,0xBC21
+,0x00A0
+,0xBC02
+,0x07CA
+,0x41C0
+,0xBC21
+,0x4208
+,0xBC02
+,0x07CA
+,0x4380
+,0xBC21
+,0x2800
+,0xBC02
+,0x07CA
+,0x4E04
+,0xBC00
+,0x08E6
+,0x4344
+,0xBC25
+,0x0400
+,0x2620
+,0x8F06
+,0xBC02
+,0x07F0
+,0x5404
+,0x4025
+,0xBC02
+,0x07FB
+,0xBC00
+,0x06C1
+,0xBC02
+,0x07FB
+,0x5404
+,0x4025
+,0xBC02
+,0x07F0
+,0xBC00
+,0x06C1
+,0xBDC8
+,0x404E
+,0x8E00
+,0xFA11
+,0xBC00
+,0x0630
+,0x8E00
+,0x8E00
+,0x8E00
+,0xBC21
+,0x0002
+,0xBC20
+,0x2008
+,0xBC00
+,0x01BB
+,0xBC21
+,0x033F
+,0xA202
+,0x0083
+,0xFB11
+,0x8EA2
+,0xBC20
+,0x2008
+,0x7010
+,0x4FF5
+,0xBC22
+,0x201A
+,0xBC00
+,0x0161
+,0x4044
+,0xBC25
+,0x1000
+,0xBC02
+,0x07F0
+,0x4E24
+,0xBC00
+,0x0705
+,0xBC22
+,0x399E
+,0xBC23
+,0x199E
+,0xBC00
+,0x078A
+,0xBC24
+,0x2080
+,0x6C88
+,0x3A10
+,0xFA94
+,0xB548
+,0x0005
+,0xBC00
+,0x0E9F
+,0xE902
+,0xBC26
+,0x2023
+,0xDFE4
+,0xBC24
+,0x2000
+,0xFAD6
+,0x0934
+,0x26C0
+,0x8F01
+,0xBC26
+,0x3056
+,0x8D02
+,0xBC26
+,0x31F9
+,0xCFE4
+,0xE9FE
+,0xBC00
+,0x0FED
+,0xBC20
+,0x2090
+,0xBC21
+,0x0100
+,0xFA12
+,0xE902
+,0x0851
+,0x6984
+,0x1FD5
+,0x8F37
+,0x8E00
+,0x8D03
+,0x8E00
+,0xBC20
+,0x2090
+,0xBC21
+,0x8000
+,0xFA10
+,0x0801
+,0x2600
+,0x8FF5
+,0xBC20
+,0x2090
+,0xBC21
+,0x2091
+,0x714F
+,0xBA10
+,0xBC22
+,0x666D
+,0x7028
+,0xBB32
+,0x71F8
+,0xBB32
+,0xA203
+,0x0457
+,0x0802
+,0xA204
+,0x0458
+,0x6980
+,0x3B33
+,0xFB34
+,0xBC22
+,0x2545
+,0xA31E
+,0x0459
+,0xFB32
+,0x8F0C
+,0x2601
+,0x4FE1
+,0x8F0D
+,0x2602
+,0xBC21
+,0x0380
+,0x8F09
+,0x2683
+,0x4001
+,0x8F05
+,0xBC02
+,0x40E7
+,0x8D04
+,0xBC21
+,0x03FF
+,0xA301
+,0x0456
+,0xA301
+,0x0455
+,0xA200
+,0x0458
+,0xA201
+,0x0457
+,0x260F
+,0x8F02
+,0x8E00
+,0x8C03
+,0x3401
+,0x3449
+,0x4000
+,0xCFD5
+,0xA300
+,0x0458
+,0x8EC0
+,0xE9FE
+,0xA301
+,0x0457
+,0xBC22
+,0x3105
+,0xA200
+,0x0313
+,0x77DE
+,0xBA52
+,0x3BC2
+,0xBC22
+,0x2091
+,0xBC3C
+,0x02E0
+,0xBC23
+,0x666D
+,0x7000
+,0xFB53
+,0x700E
+,0xAA18
+,0xBC24
+,0x0B12
+,0xFB54
+,0x6D36
+,0x7C1C
+,0x6C8D
+,0x7B54
+,0x8FF9
+,0xA203
+,0x0355
+,0xFB53
+,0xA203
+,0x035A
+,0xFB53
+,0xA203
+,0x0464
+,0xBC24
+,0x2004
+,0xFB53
+,0xFA94
+,0xA203
+,0x047F
+,0xFB54
+,0xFB53
+,0xA204
+,0x0480
+,0xFB54
+,0xA203
+,0x0481
+,0xFB53
+,0xA204
+,0x0361
+,0xA203
+,0x0362
+,0xFB54
+,0xFB53
+,0xBC23
+,0x5A5A
+,0xFB53
+,0x8EC0
+,0xBC23
+,0x2545
+,0xFB53
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+};
+
+const unsigned short bin_patch_E2[] = { 
+0x2000
+,0x21FF
+,0x8E00
+,0x8E00
+,0x8E00
+,0xBC21
+,0x0002
+,0xBC20
+,0x2008
+,0xBC00
+,0x01A9
+,0xBC21
+,0x033F
+,0xA202
+,0x0083
+,0xFB11
+,0x8EA2
+,0xBC20
+,0x2008
+,0x7010
+,0x4FF5
+,0xBC22
+,0x201A
+,0xBC00
+,0x014F
+,0x240C
+,0xA301
+,0x047F
+,0xA30F
+,0x0480
+,0xA30E
+,0x0481
+,0xBC00
+,0x1353
+,0x5380
+,0xBC21
+,0xAC40
+,0xBC02
+,0x07EA
+,0x4380
+,0xBC21
+,0x2C00
+,0xBC02
+,0x07EA
+,0x43A0
+,0xBC21
+,0xFB40
+,0xBC02
+,0x07EA
+,0x43C0
+,0xBC21
+,0x0546
+,0xBC02
+,0x07EA
+,0x43E0
+,0xBC21
+,0xFB3C
+,0xBC02
+,0x07EA
+,0x4400
+,0xBC21
+,0x0537
+,0xBC02
+,0x07EA
+,0x4E04
+,0xBC00
+,0x092A
+,0x4025
+,0xBC21
+,0x2023
+,0xBC22
+,0x0400
+,0xFA31
+,0x084A
+,0x2610
+,0x8F01
+,0xBC02
+,0x081B
+,0x8D02
+,0xBC02
+,0x0810
+,0x4E24
+,0xBC00
+,0x0722
+,0x4280
+,0xBC02
+,0x07EA
+,0xBC22
+,0x8018
+,0xBC23
+,0x8098
+,0xCFE0
+,0x2600
+,0x1853
+,0x42C0
+,0xBC02
+,0x07EA
+,0x4240
+,0xBC21
+,0xE400
+,0xBC02
+,0x07EA
+,0x4260
+,0xBC21
+,0x0010
+,0xBC02
+,0x07EA
+,0x4040
+,0xBC21
+,0x0FFB
+,0xBC02
+,0x07EA
+,0x4220
+,0xBC21
+,0x2020
+,0xBC02
+,0x07EA
+,0xBC20
+,0x0005
+,0x4461
+,0xBC02
+,0x07F8
+,0x4220
+,0xBC21
+,0x1020
+,0xBC02
+,0x07EA
+,0xBC20
+,0x0005
+,0x4461
+,0xBC02
+,0x07F8
+,0x4220
+,0xBC21
+,0x4020
+,0xBC02
+,0x07EA
+,0xBC20
+,0x0064
+,0x4461
+,0xBC02
+,0x07F8
+,0x4240
+,0xBC21
+,0xE407
+,0xBC02
+,0x07EA
+,0x4260
+,0xBC21
+,0x7010
+,0xBC02
+,0x07EA
+,0xBC20
+,0x0064
+,0x4461
+,0xBC02
+,0x07F8
+,0x4520
+,0xBC21
+,0x8001
+,0xBC02
+,0x07EA
+,0xBC00
+,0x0794
+,0xBC20
+,0x2090
+,0xBC21
+,0x0100
+,0xFA12
+,0xE902
+,0x0851
+,0x6984
+,0x1FD5
+,0x8F37
+,0x8E00
+,0x8D03
+,0x8E00
+,0xBC20
+,0x2090
+,0xBC21
+,0x8000
+,0xFA10
+,0x0801
+,0x2600
+,0x8FF5
+,0xBC20
+,0x2090
+,0xBC21
+,0x2091
+,0x714F
+,0xBA10
+,0xBC22
+,0x666D
+,0x7028
+,0xBB32
+,0x71F8
+,0xBB32
+,0xA203
+,0x045B
+,0x0802
+,0xA204
+,0x045C
+,0x6980
+,0x3B33
+,0xFB34
+,0xBC22
+,0x2545
+,0xA31E
+,0x045D
+,0xFB32
+,0x8F0C
+,0x2601
+,0x4FE1
+,0x8F0D
+,0x2602
+,0xBC21
+,0x0380
+,0x8F09
+,0x2683
+,0x4001
+,0x8F05
+,0xBC02
+,0x40F6
+,0x8D04
+,0xBC21
+,0x03FF
+,0xA301
+,0x045A
+,0xA301
+,0x0459
+,0xA200
+,0x045C
+,0xA201
+,0x045B
+,0x260F
+,0x8F02
+,0x8E00
+,0x8C03
+,0x3401
+,0x3449
+,0x4000
+,0xCFD5
+,0xA300
+,0x045C
+,0x8EC0
+,0xE9FE
+,0xA301
+,0x045B
+,0xBC22
+,0x3105
+,0xA200
+,0x0314
+,0x77DE
+,0xBA52
+,0x3BC2
+,0xBC22
+,0x2091
+,0xBC3C
+,0x02E1
+,0xBC23
+,0x666D
+,0x7000
+,0xFB53
+,0x700E
+,0xAA18
+,0xBC24
+,0x0B12
+,0xFB54
+,0x6D36
+,0x7C1C
+,0x6C8D
+,0x7B54
+,0x8FF9
+,0xA203
+,0x0356
+,0xFB53
+,0xA203
+,0x035D
+,0xFB53
+,0xA203
+,0x0468
+,0xBC24
+,0x2004
+,0xFB53
+,0xFA94
+,0xA203
+,0x0483
+,0xFB54
+,0xFB53
+,0xA204
+,0x0484
+,0xFB54
+,0xA203
+,0x0485
+,0xFB53
+,0xA204
+,0x0364
+,0xA203
+,0x0365
+,0xFB54
+,0xFB53
+,0xBC23
+,0x5A5A
+,0xFB53
+,0x8EC0
+,0xBC23
+,0x2545
+,0xFB53
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+};
+
+const unsigned short bin_coeff_E1[] = { 
+0x0000
+,0x01FF
+,0x0400
+,0x0006
+,0x2AAB
+,0x0324
+,0x0324
+,0x0324
+,0x010C
+,0x010C
+,0x010C
+,0x1111
+,0x1259
+,0x0001
+,0x005A
+,0x0E9B
+,0x0FFF
+,0x0FFF
+,0x0008
+,0x0001
+,0x0001
+,0x0CCD
+,0xFFE0
+,0xFFD8
+,0x00FF
+,0xFFAC
+,0xFFBC
+,0xFF00
+,0x0020
+,0x0048
+,0x0050
+,0x0050
+,0x000E
+,0x0002
+,0x7000
+,0x0800
+,0xFFF8
+,0x0008
+,0x002B
+,0xFFF6
+,0xFFF8
+,0xFFFE
+,0x0003
+,0x0008
+,0x000D
+,0x000F
+,0x0014
+,0x0019
+,0x0000
+,0x0800
+,0x6580
+,0x0000
+,0x0000
+,0x7FFF
+,0x0008
+,0x0078
+,0xFEF5
+,0xFEE8
+,0x0003
+,0x0080
+,0x0080
+,0x0080
+,0x0300
+,0x0006
+,0xC080
+,0xF000
+,0x0660
+,0xDA80
+,0x0000
+,0x0001
+,0x0001
+,0xFFE4
+,0xFFE8
+,0x0080
+,0x0034
+,0x0001
+,0xFFFF
+,0x0001
+,0xFFFE
+,0x3AC0
+,0x3340
+,0x2BC0
+,0x07C0
+,0x05C0
+,0x03E0
+,0x0008
+,0x1000
+,0x2000
+,0xFF01
+,0xFFE5
+,0xFFE9
+,0x0DA8
+,0x000E
+,0xF75E
+,0x1136
+,0xEC7B
+,0x0D3C
+,0xFA9A
+,0xFC47
+,0xF58B
+,0x1055
+,0x3DDA
+,0x3DDA
+,0x1055
+,0xF58B
+,0xFC47
+,0x1B17
+,0x362A
+,0x1B17
+,0x67DA
+,0xA798
+,0xFDA6
+,0xF8BE
+,0xF36E
+,0xF0D4
+,0xF368
+,0xFB18
+,0x04E8
+,0x0C98
+,0x0F2C
+,0x0C92
+,0x0742
+,0x025A
+,0x0028
+,0x0029
+,0x0028
+,0x0029
+,0x0028
+,0x0029
+,0x0028
+,0x0028
+,0x0029
+,0x0028
+,0x0029
+,0x0028
+,0x0028
+,0x0029
+,0x0028
+,0x0029
+,0x0028
+,0x0029
+,0x0028
+,0x712C
+,0xF1A8
+,0xF9D4
+,0x208E
+,0x4BC2
+,0xF280
+,0xF280
+,0x4BC2
+,0x208E
+,0xF9D4
+,0xF1A8
+,0x712C
+,0x0000
+,0x0200
+,0x0100
+,0x0080
+,0x0040
+,0x0020
+,0x0010
+,0x0008
+,0x0004
+,0x0002
+,0x0001
+,0x02DC
+,0x016E
+,0x00B7
+,0x0287
+,0x039F
+,0x0313
+,0x0355
+,0x0376
+,0x01BB
+,0x0201
+,0x03DC
+,0x01EE
+,0x00F7
+,0x02A7
+,0x038F
+,0x031B
+,0x00FC
+,0x00FC
+,0x0198
+,0x0198
+,0x0168
+,0x0350
+,0x01B4
+,0x01B4
+,0x0089
+,0x002C
+,0x0058
+,0x002C
+,0x0400
+,0x0000
+,0x0003
+,0xFAED
+,0xFED0
+,0x09E2
+,0x166A
+,0x1BEF
+,0x166A
+,0x09E2
+,0xFED0
+,0xFAED
+,0x2715
+,0x58EB
+,0x58EB
+,0x2715
+,0xFF8F
+,0xFF25
+,0xFEA1
+,0xFE12
+,0xFD8A
+,0xFD26
+,0xFD04
+,0xFD43
+,0xFE00
+,0xFF4E
+,0x0139
+,0x03B9
+,0x06BB
+,0x0A1A
+,0x0DA5
+,0x111F
+,0x144B
+,0x16EC
+,0x18CC
+,0x19C7
+,0x19C7
+,0x18CC
+,0x16EC
+,0x144B
+,0x111F
+,0x0DA5
+,0x0A1A
+,0x06BB
+,0x03B9
+,0x0139
+,0xFF4E
+,0xFE00
+,0xFD43
+,0xFD04
+,0xFD26
+,0xFD8A
+,0xFE12
+,0xFEA1
+,0xFF25
+,0xFF8F
+,0x0002
+,0x0004
+,0x47B3
+,0xBAC5
+,0x0B85
+,0x0005
+,0x299A
+,0x0004
+,0x000A
+,0x0660
+,0x0CCD
+,0x0003
+,0x0006
+,0x0080
+,0x002C
+,0x0020
+,0x0027
+,0xFF4F
+,0xFDB1
+,0xFE2E
+,0x0465
+,0x0EF1
+,0x161E
+,0x1382
+,0x0983
+,0x007B
+,0xFD66
+,0xFE7D
+,0xFFE2
+,0x0031
+,0x000D
+,0x4000
+,0xFD24
+,0x513A
+,0xCAEC
+,0x3514
+,0xAEC6
+,0x02DC
+,0x4000
+,0xEFB5
+,0x6EAE
+,0x8DAB
+,0x7255
+,0x9152
+,0x104B
+,0x2518
+,0x1FBB
+,0x14A2
+,0x0D6A
+,0x08B9
+,0x05AC
+,0x03B0
+,0x0266
+,0x018F
+,0x0104
+,0x00A9
+,0x006E
+,0x0047
+,0x0001
+,0x0164
+,0x019A
+,0x0001
+,0x0002
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x7FFF
+,0x0000
+,0x0100
+,0xF500
+,0x1C00
+,0x5A00
+,0x0100
+,0xFF00
+,0xF800
+,0x2000
+,0x4F00
+,0x0100
+,0xFE00
+,0xFC00
+,0x2200
+,0x4700
+,0x0000
+,0xFD00
+,0x0100
+,0x2300
+,0x3D00
+,0xFF00
+,0xFE00
+,0x0500
+,0x2200
+,0x3600
+,0xFF00
+,0xFF00
+,0x0900
+,0x2100
+,0x2F00
+,0x0000
+,0x0100
+,0x0C00
+,0x1F00
+,0x2900
+,0x0000
+,0x0300
+,0x0E00
+,0x1D00
+,0x2500
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x7FFF
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0004
+,0x0008
+,0x0308
+,0x0312
+,0x01CC
+,0x017C
+,0x0019
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0xE000
+,0x1840
+,0xC880
+,0xFFEE
+,0x0000
+,0x4000
+,0x2680
+,0xFF81
+,0xE000
+,0x5000
+,0xD080
+,0xFFB3
+,0xF800
+,0x4500
+,0xD380
+,0xFFE2
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0F80
+,0xDB80
+,0x21C0
+,0xFFCC
+,0x0000
+,0xC680
+,0x0540
+,0x0023
+,0x33C0
+,0xDAC0
+,0x5900
+,0xFFDA
+,0x0AC0
+,0xDF80
+,0x1940
+,0xFFF7
+,0x7FFF
+,0x50C3
+,0x47FA
+,0x4026
+,0x392C
+,0x32F5
+,0x2D6A
+,0x287A
+,0x2413
+,0x2027
+,0x1CA8
+,0x198A
+,0x16C3
+,0x1449
+,0x1214
+,0x101D
+,0x0E5D
+,0x0CCD
+,0x0B68
+,0x0A2B
+,0x0910
+,0x0813
+,0x0015
+,0x0002
+,0x0080
+,0x2848
+,0x051F
+,0x0001
+,0x0010
+,0xFC40
+,0xFC40
+,0xFD94
+,0xFD80
+,0xFE80
+,0xFE80
+,0xFE7C
+,0xFE7F
+,0x02F4
+,0x0001
+,0x0080
+,0x0080
+,0x1000
+,0x0080
+,0x1000
+,0x1000
+,0x0400
+,0x599A
+,0x199A
+,0x0666
+,0x0021
+,0x2000
+,0x2000
+,0x2000
+,0xFFE4
+,0x0032
+,0x000A
+,0x2000
+,0x4000
+,0x0800
+,0x0400
+,0x000C
+,0x0005
+,0x000C
+,0x00FF
+,0x083D
+,0x4000
+,0x062F
+,0x404C
+,0x01B9
+,0x4052
+,0x0155
+,0x405B
+,0x0704
+,0x4069
+,0x0786
+,0x4071
+,0x0E9A
+,0x4077
+,0x0FEB
+,0x4080
+,0x0000
+,0x0000
+,0xFFD5
+,0x0001
+,0x0375
+,0x001E
+,0x0AAB
+,0x2000
+,0x2AAB
+,0x0040
+,0x0005
+,0x001E
+,0x4093
+,0xFEE0
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+};
+
+const unsigned short bin_coeff_E2[] = { 
+0x0000
+,0x01FF
+,0x0400
+,0x0006
+,0x2AAB
+,0x0324
+,0x0324
+,0x0324
+,0x010C
+,0x010C
+,0x010C
+,0x1111
+,0x1259
+,0x0001
+,0x005A
+,0x0E9B
+,0x0FFF
+,0x0FFF
+,0x0020
+,0x0001
+,0x0001
+,0x0CCD
+,0xFFE0
+,0xFFD8
+,0x00FF
+,0xFFAC
+,0xFFBC
+,0xFF00
+,0x0020
+,0x0048
+,0x0050
+,0x0050
+,0x000E
+,0x0002
+,0x7000
+,0x0800
+,0xFFF8
+,0x0008
+,0x002B
+,0xFFF6
+,0xFFF8
+,0xFFFE
+,0x0003
+,0x0008
+,0x000D
+,0x000F
+,0x0014
+,0x0019
+,0x0000
+,0x0800
+,0x6580
+,0x0000
+,0x0000
+,0x7FFF
+,0x0008
+,0x0078
+,0xFEF5
+,0xFEE8
+,0x0003
+,0x0080
+,0x0080
+,0x0080
+,0x0300
+,0x0006
+,0xC080
+,0xF000
+,0x0660
+,0xDA80
+,0x0000
+,0x0001
+,0x0001
+,0xFFE4
+,0xFFE8
+,0x0080
+,0x0034
+,0x0001
+,0xFFFF
+,0x0001
+,0xFFFE
+,0x3AC0
+,0x3340
+,0x2BC0
+,0x07C0
+,0x05C0
+,0x03E0
+,0x0008
+,0x1000
+,0x2000
+,0xFF01
+,0xFFE5
+,0xFFE9
+,0x0DA8
+,0x000E
+,0xF75E
+,0x1136
+,0xEC7B
+,0x0D3C
+,0xFA9A
+,0xFC47
+,0xF58B
+,0x1055
+,0x3DDA
+,0x3DDA
+,0x1055
+,0xF58B
+,0xFC47
+,0x1B17
+,0x362A
+,0x1B17
+,0x67DA
+,0xA798
+,0xFDA6
+,0xF8BE
+,0xF36E
+,0xF0D4
+,0xF368
+,0xFB18
+,0x04E8
+,0x0C98
+,0x0F2C
+,0x0C92
+,0x0742
+,0x025A
+,0x0028
+,0x0029
+,0x0028
+,0x0029
+,0x0028
+,0x0029
+,0x0028
+,0x0028
+,0x0029
+,0x0028
+,0x0029
+,0x0028
+,0x0028
+,0x0029
+,0x0028
+,0x0029
+,0x0028
+,0x0029
+,0x0028
+,0x712C
+,0xF1A8
+,0xF9D4
+,0x208E
+,0x4BC2
+,0xF280
+,0xF280
+,0x4BC2
+,0x208E
+,0xF9D4
+,0xF1A8
+,0x712C
+,0x0000
+,0x0200
+,0x0100
+,0x0080
+,0x0040
+,0x0020
+,0x0010
+,0x0008
+,0x0004
+,0x0002
+,0x0001
+,0x02DC
+,0x016E
+,0x00B7
+,0x0287
+,0x039F
+,0x0313
+,0x0355
+,0x0376
+,0x01BB
+,0x0201
+,0x03DC
+,0x01EE
+,0x00F7
+,0x02A7
+,0x038F
+,0x031B
+,0x00FC
+,0x00FC
+,0x0198
+,0x0198
+,0x0168
+,0x0350
+,0x01B4
+,0x01B4
+,0x0089
+,0x002C
+,0x0058
+,0x002C
+,0x0400
+,0x0000
+,0x0003
+,0xFAED
+,0xFED0
+,0x09E2
+,0x166A
+,0x1BEF
+,0x166A
+,0x09E2
+,0xFED0
+,0xFAED
+,0x2715
+,0x58EB
+,0x58EB
+,0x2715
+,0xFF8F
+,0xFF25
+,0xFEA1
+,0xFE12
+,0xFD8A
+,0xFD26
+,0xFD04
+,0xFD43
+,0xFE00
+,0xFF4E
+,0x0139
+,0x03B9
+,0x06BB
+,0x0A1A
+,0x0DA5
+,0x111F
+,0x144B
+,0x16EC
+,0x18CC
+,0x19C7
+,0x19C7
+,0x18CC
+,0x16EC
+,0x144B
+,0x111F
+,0x0DA5
+,0x0A1A
+,0x06BB
+,0x03B9
+,0x0139
+,0xFF4E
+,0xFE00
+,0xFD43
+,0xFD04
+,0xFD26
+,0xFD8A
+,0xFE12
+,0xFEA1
+,0xFF25
+,0xFF8F
+,0x0002
+,0x0004
+,0x47B3
+,0xBAC5
+,0x0B85
+,0x0005
+,0x299A
+,0x0004
+,0x000A
+,0x0660
+,0x0CCD
+,0x0003
+,0x0006
+,0x0080
+,0x002C
+,0x0020
+,0x0027
+,0xFF4F
+,0xFDB1
+,0xFE2E
+,0x0465
+,0x0EF1
+,0x161E
+,0x1382
+,0x0983
+,0x007B
+,0xFD66
+,0xFE7D
+,0xFFE2
+,0x0031
+,0x000D
+,0x4000
+,0xFD24
+,0x513A
+,0xCAEC
+,0x3514
+,0xAEC6
+,0x02DC
+,0x4000
+,0xEFB5
+,0x6EAE
+,0x8DAB
+,0x7255
+,0x9152
+,0x104B
+,0x2518
+,0x1FBB
+,0x14A2
+,0x0D6A
+,0x08B9
+,0x05AC
+,0x03B0
+,0x0266
+,0x018F
+,0x0104
+,0x00A9
+,0x006E
+,0x0047
+,0x0001
+,0x0164
+,0x019A
+,0x0001
+,0x0002
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x7FFF
+,0x0000
+,0x0100
+,0xF500
+,0x1C00
+,0x5A00
+,0x0100
+,0xFF00
+,0xF800
+,0x2000
+,0x4F00
+,0x0100
+,0xFE00
+,0xFC00
+,0x2200
+,0x4700
+,0x0000
+,0xFD00
+,0x0100
+,0x2300
+,0x3D00
+,0xFF00
+,0xFE00
+,0x0500
+,0x2200
+,0x3600
+,0xFF00
+,0xFF00
+,0x0900
+,0x2100
+,0x2F00
+,0x0000
+,0x0100
+,0x0C00
+,0x1F00
+,0x2900
+,0x0000
+,0x0300
+,0x0E00
+,0x1D00
+,0x2500
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x7FFF
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0004
+,0x0008
+,0x0308
+,0x0312
+,0x01CC
+,0x017C
+,0x0019
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0xE000
+,0x1840
+,0xC880
+,0xFFEE
+,0x0000
+,0x4000
+,0x2680
+,0xFF81
+,0xE000
+,0x5000
+,0xD080
+,0xFFB3
+,0xF800
+,0x4500
+,0xD380
+,0xFFE2
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0F80
+,0xDB80
+,0x21C0
+,0xFFCC
+,0x0000
+,0xC680
+,0x0540
+,0x0023
+,0x33C0
+,0xDAC0
+,0x5900
+,0xFFDA
+,0x0AC0
+,0xDF80
+,0x1940
+,0xFFF7
+,0x7FFF
+,0x50C3
+,0x47FA
+,0x4026
+,0x392C
+,0x32F5
+,0x2D6A
+,0x287A
+,0x2413
+,0x2027
+,0x1CA8
+,0x198A
+,0x16C3
+,0x1449
+,0x1214
+,0x101D
+,0x0E5D
+,0x0CCD
+,0x0B68
+,0x0A2B
+,0x0910
+,0x0813
+,0x0015
+,0x0002
+,0x0080
+,0x2848
+,0x051F
+,0x0001
+,0x0010
+,0xFC40
+,0xFC40
+,0xFD94
+,0xFD80
+,0xFE80
+,0xFE80
+,0xFE7C
+,0xFE7F
+,0x02F4
+,0x0001
+,0x0080
+,0x0080
+,0x1000
+,0x0080
+,0x1000
+,0x1000
+,0x0400
+,0x599A
+,0x199A
+,0x0666
+,0x0021
+,0x2000
+,0x2000
+,0x2000
+,0xFFE4
+,0x0032
+,0x000A
+,0x2000
+,0x4000
+,0x0800
+,0x0400
+,0x000C
+,0x0005
+,0x000C
+,0x0038
+,0x01A7
+,0x4000
+,0x0143
+,0x4009
+,0x0000
+,0x0000
+,0x0929
+,0x4020
+,0x0721
+,0x4041
+,0x0755
+,0x4052
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0xFFD5
+,0x0001
+,0x0375
+,0x001E
+,0x0AAB
+,0x2000
+,0x2AAB
+,0x0040
+,0x0005
+,0x001E
+,0x0001
+,0xFEE0
+,0xFED8
+,0xFED8
+,0x0000
+,0x0040
+,0x40A2
+,0x0000
+};
+
+const unsigned short bin_hw_coeff[] = {
+0x0000
+,0x0027
+,0xfffd
+,0xfffc
+,0x0002
+,0x000a
+,0x0005
+,0xfff4
+,0xffed
+,0x0004
+,0x0024
+,0x0018
+,0xffd8
+,0xffb1
+,0x0006
+,0x00cd
+,0x0179
+,0x0001
+,0xfffd
+,0x0004
+,0x0000   
+,0x000b
+,0xffe0
+,0x0047
+,0xff75
+,0x0134
+,0x04c4
+,0xff9c
+,0x000f
+,0x0007
+,0xfff7
+,0x0006
+,0x0001
+,0x0008
+,0xffdf
+,0x005d
+,0xff18
+,0x034a
+,0xff81
+,0x03d9
+,0x00a6
+,0xfffe
+,0x0012
+,0xffa6
+,0x0000
+};
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6626/inc/mt6626_fm.h b/drivers/mtk_wcn_combo/drv_fm/mt6626/inc/mt6626_fm.h
new file mode 100755 (executable)
index 0000000..6617cdd
--- /dev/null
@@ -0,0 +1,82 @@
+/* mt6628_fm.h
+ *
+ * (C) Copyright 2009 
+ * MediaTek <www.MediaTek.com>
+ * Hongcheng <hongcheng.xia@MediaTek.com>
+ *
+ * MT6626 FM Radio Driver --  head file
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __MT6626_FM_H__
+#define __MT6626_FM_H__
+
+#include "fm_typedef.h"
+
+//#define FM_PowerOn_with_ShortAntenna
+#define MT6626_RSSI_TH_LONG    0xFF01      //FM radio long antenna RSSI threshold(11.375dBuV)
+#define MT6626_RSSI_TH_SHORT   0xFEE0      //FM radio short antenna RSSI threshold(-1dBuV)
+#define MT6626_CQI_TH          0x00E9      //FM radio Channel quality indicator threshold(0x0000~0x00FF)
+#define MT6626_SEEK_SPACE      1           //FM radio seek space,1:100KHZ; 2:200KHZ
+#define MT6626_SCAN_CH_SIZE    40          //FM radio scan max channel size
+#define MT6626_BAND            1           //FM radio band, 1:87.5MHz~108.0MHz; 2:76.0MHz~90.0MHz; 3:76.0MHz~108.0MHz; 4:special
+#define MT6626_BAND_FREQ_L     875         //FM radio special band low freq(Default 87.5MHz)
+#define MT6626_BAND_FREQ_H     1080        //FM radio special band high freq(Default 108.0MHz)
+#define MT6626_DEEMPHASIS_50us TRUE
+
+//customer need customize the I2C port
+#ifdef MT6516
+#define MT6626_I2C_PORT   2
+#else 
+#define MT6626_I2C_PORT   0
+#endif
+
+#define MT6626_SLAVE_ADDR    0xE0      //0x70 7-bit address
+#define MT6626_MAX_COUNT     100
+#define MT6626_SCANTBL_SIZE  16                //16*uinit16_t
+
+#define AFC_ON  0x01
+#if AFC_ON
+#define FM_MAIN_CTRL_INIT  0x480
+#else
+#define FM_MAIN_CTRL_INIT  0x080
+#endif
+
+//FM_MAIN_EXTINTRMASK
+#define FM_EXT_STC_DONE_MASK 0x01
+#define FM_EXT_RDS_MASK      0x20
+
+#define MT6626_FM_STC_DONE_TIMEOUT 12  //second
+
+//FM_MAIN_CHANDETSTAT
+#define FM_MAIN_CHANDET_MASK   0x3FF0  // D4~D13 in address 6FH
+#define FM_MAIN_CHANDET_SHIFT  0x04
+#define FM_HOST_CHAN   0x3FF0
+
+//FM_MAIN_CFG1(0x36) && FM_MAIN_CFG2(0x37)
+#define MT6626_FM_SEEK_UP       0x0
+#define MT6626_FM_SEEK_DOWN     0x01
+#define MT6626_FM_SCAN_UP       0x0
+#define MT6626_FM_SCAN_DOWN     0x01
+#define MT6626_FM_SPACE_INVALID 0x0
+#define MT6626_FM_SPACE_50K     0x01
+#define MT6626_FM_SPACE_100K    0x02
+#define MT6626_FM_SPACE_200K    0x04 
+
+#define ext_clk                                //if define ext_clk use external reference clock or mask will use internal
+#define MT6626_DEV                     "MT6626"   
+
+#endif //end of #ifndef __MT6626_FM_H__
+
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6626/inc/mt6626_fm_cmd.h b/drivers/mtk_wcn_combo/drv_fm/mt6626/inc/mt6626_fm_cmd.h
new file mode 100755 (executable)
index 0000000..3e3e4d0
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef __MT6626_FM_CMD_H__
+#define __MT6626_FM_CMD_H__
+
+#include <linux/types.h>
+#include "fm_typedef.h"
+
+/* FM basic-operation's opcode */
+#define FM_BOP_BASE (0x80)
+enum {
+    FM_WRITE_BASIC_OP       = (FM_BOP_BASE + 0x00),
+    FM_UDELAY_BASIC_OP      = (FM_BOP_BASE + 0x01),
+    FM_RD_UNTIL_BASIC_OP    = (FM_BOP_BASE + 0x02),
+    FM_MODIFY_BASIC_OP      = (FM_BOP_BASE + 0x03),
+    FM_MSLEEP_BASIC_OP      = (FM_BOP_BASE + 0x04),
+    FM_MAX_BASIC_OP         = (FM_BOP_BASE + 0x05)
+};
+
+/* FM BOP's size */
+#define FM_WRITE_BASIC_OP_SIZE      (3)
+#define FM_UDELAY_BASIC_OP_SIZE     (4)
+#define FM_RD_UNTIL_BASIC_OP_SIZE   (5)
+#define FM_MODIFY_BASIC_OP_SIZE     (5)
+#define FM_MSLEEP_BASIC_OP_SIZE     (4)
+
+fm_s32 mt6626_pwrup_clock_on(fm_u8 *tx_buf, fm_s32 tx_buf_size);
+fm_s32 mt6626_pwrup_digital_init_1(fm_u8 *tx_buf, fm_s32 tx_buf_size);
+fm_s32 mt6626_pwrup_digital_init_2(fm_u8 *tx_buf, fm_s32 tx_buf_size);
+fm_s32 mt6626_pwrdown(fm_u8 *tx_buf, fm_s32 tx_buf_size);
+fm_s32 mt6626_rampdown(fm_u8 *tx_buf, fm_s32 tx_buf_size);
+fm_s32 mt6626_tune(fm_u8 *tx_buf, fm_s32 tx_buf_size, fm_u16 freq);
+fm_s32 mt6626_seek(fm_u8 *tx_buf, fm_s32 tx_buf_size, fm_u16 seekdir, fm_u16 space, fm_u16 max_freq, fm_u16 min_freq);
+fm_s32 mt6626_scan(fm_u8 *tx_buf, fm_s32 tx_buf_size, fm_u16 scandir, fm_u16 space, fm_u16 max_freq, fm_u16 min_freq);
+fm_s32 mt6626_get_reg(fm_u8 *tx_buf, fm_s32 tx_buf_size, fm_u8 addr);
+fm_s32 mt6626_set_reg(fm_u8 *tx_buf, fm_s32 tx_buf_size, fm_u8 addr, fm_u16 value);
+fm_s32 mt6626_patch_download(fm_u8 *tx_buf, fm_s32 tx_buf_size, fm_u8 seg_num, fm_u8 seg_id, const fm_u8 *src, fm_s32 seg_len);
+fm_s32 mt6626_coeff_download(fm_u8 *tx_buf, fm_s32 tx_buf_size, fm_u8 seg_num, fm_u8 seg_id, const fm_u8 *src, fm_s32 seg_len);
+fm_s32 mt6626_hwcoeff_download(fm_u8 *tx_buf, fm_s32 tx_buf_size, fm_u8 seg_num, fm_u8 seg_id, const fm_u8 *src, fm_s32 seg_len);
+fm_s32 mt6626_rom_download(fm_u8 *tx_buf, fm_s32 tx_buf_size, fm_u8 seg_num, fm_u8 seg_id, const fm_u8 *src, fm_s32 seg_len);
+
+#endif
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6626/inc/mt6626_fm_lib.h b/drivers/mtk_wcn_combo/drv_fm/mt6626/inc/mt6626_fm_lib.h
new file mode 100755 (executable)
index 0000000..aca4094
--- /dev/null
@@ -0,0 +1,77 @@
+#ifndef __MT6626_FM_LIB_H__
+#define __MT6626_FM_LIB_H__
+
+#include "fm_typedef.h"
+
+enum {
+    DSPPATCH = 0xFFF9,
+    USDELAY = 0xFFFA,
+    MSDELAY = 0xFFFB,
+    HW_VER = 0xFFFD,
+    POLL_N = 0xFFFE, //poling check if bit(n) is '0'
+    POLL_P = 0xFFFF, //polling check if bit(n) is '1'
+};
+
+enum {
+    FM_PUS_DSPPATCH = DSPPATCH,
+    FM_PUS_USDELAY = USDELAY,
+    FM_PUS_MSDELAY = MSDELAY,
+    FM_PUS_HW_VER = HW_VER,
+    FM_PUS_POLL_N = POLL_N, //poling check if bit(n) is '0'
+    FM_PUS_POLL_P = POLL_P, //polling check if bit(n) is '1'
+    FM_PUS_MAX
+};
+
+enum {
+    DSP_PATH = 0x02,
+    DSP_COEFF = 0x03,
+    DSP_HW_COEFF = 0x04
+};
+
+enum IMG_TYPE {
+    IMG_WRONG = 0,
+    IMG_ROM,
+    IMG_PATCH,
+    IMG_COEFFICIENT,
+    IMG_HW_COEFFICIENT
+};
+
+enum {
+    mt6626_E1 = 0,
+    mt6626_E2
+};
+
+enum {
+    FM_LONG_ANA = 0,
+    FM_SHORT_ANA
+};
+
+struct ctrl_word_operation {
+    fm_u16 addr;
+    fm_u16 and;
+    fm_u16 or;
+};
+
+enum {
+    MT66x6_BT = 0,
+    MT66x6_FM,
+    MT66x6_MAX
+};
+
+enum {
+    MT6626_I2S_ON = 0,
+    MT6626_I2S_OFF
+};
+
+enum {
+    MT6626_I2S_MASTER = 0,
+    MT6626_I2S_SLAVE
+};
+
+enum {
+    MT6626_I2S_32K = 0,
+    MT6626_I2S_44K,
+    MT6626_I2S_48K
+};
+
+#endif
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6626/inc/mt6626_fm_link.h b/drivers/mtk_wcn_combo/drv_fm/mt6626/inc/mt6626_fm_link.h
new file mode 100755 (executable)
index 0000000..4a630f0
--- /dev/null
@@ -0,0 +1,68 @@
+/* mt6626_fm_ctrl_link.h
+ *
+ * (C) Copyright 2009
+ * MediaTek <www.MediaTek.com>
+ * Hongcheng <hongcheng.xia@MediaTek.com>
+ *
+ * MT6626 FM Radio Driver -- setup data link
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __MT6626_FM_LINK_H__
+#define __MT6626_FM_LINK_H__
+
+#include <linux/wait.h>
+#include "fm_link.h"
+#include "fm_utils.h"
+
+#define RX_BUF_SIZE 128
+#define TX_BUF_SIZE 1024
+
+#define SW_RETRY_CNT            (2)
+#define SW_RETRY_CNT_MAX        (5)
+#define SW_WAIT_TIMEOUT_MAX     (100)
+
+// FM operation timeout define for error handle
+#define TEST_TIMEOUT            (3)
+#define FSPI_EN_TIMEOUT         (3)
+#define FSPI_MUXSEL_TIMEOUT     (3)
+#define FSPI_RD_TIMEOUT         (3)
+#define FSPI_WR_TIMEOUT         (3)
+#define I2C_RD_TIMEOUT          (3)
+#define I2C_WR_TIMEOUT          (3)
+#define EN_TIMEOUT              (5)
+#define RST_TIMEOUT             (3)
+#define TUNE_TIMEOUT            (3)
+#define SEEK_TIMEOUT            (10)
+#define SCAN_TIMEOUT            (15) //usualy scan will cost 10 seconds 
+#define RDS_RX_EN_TIMEOUT       (3)
+#define RDS_DATA_TIMEOUT        (100)
+#define RAMPDOWN_TIMEOUT        (3)
+#define MCUCLK_TIMEOUT          (3)
+#define MODEMCLK_TIMEOUT        (3)
+#define RDS_TX_TIMEOUT          (3)
+#define PATCH_TIMEOUT           (5)
+#define COEFF_TIMEOUT           (5)
+#define HWCOEFF_TIMEOUT         (5)
+#define ROM_TIMEOUT             (5)
+
+struct fm_link_event {
+    struct fm_flag_event *ln_event;
+    struct fm_res_ctx result; // seek/scan/read/RDS
+};
+
+
+#endif
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6626/inc/mt6626_fm_reg.h b/drivers/mtk_wcn_combo/drv_fm/mt6626/inc/mt6626_fm_reg.h
new file mode 100755 (executable)
index 0000000..4c0b5ad
--- /dev/null
@@ -0,0 +1,84 @@
+#ifndef __MT6626_FM_REG_H__
+#define __MT6626_FM_REG_H__
+
+enum MT6626_REG{ 
+       FM_MAIN_CG1_CTRL = 0x60,
+       FM_MAIN_CG2_CTRL = 0x61,
+    FM_MAIN_HWVER = 0x62,
+    FM_MAIN_CTRL = 0x63,
+    FM_CHANNEL_SET = 0x65,
+    FM_MAIN_CFG1 = 0x66,
+    FM_MAIN_CFG2 = 0x67,
+    FM_MAIN_MCLKDESENSE = 0x38,
+    FM_MAIN_INTR = 0x69,
+    FM_MAIN_INTRMASK = 0x6A,
+    FM_MAIN_EXTINTRMASK = 0x6B,
+    FM_RSSI_IND = 0x6C,
+    FM_RSSI_TH = 0x6D,
+    FM_MAIN_RESET = 0x6E,
+    FM_MAIN_CHANDETSTAT = 0x6F,  
+    FM_RDS_CFG0 = 0x80,
+    FM_RDS_INFO = 0x81,
+    FM_RDS_DATA_REG = 0x82,
+    FM_RDS_GOODBK_CNT = 0x83,
+    FM_RDS_BADBK_CNT = 0x84,
+    FM_RDS_PWDI = 0x85,
+    FM_RDS_PWDQ = 0x86,
+    FM_RDS_FIFO_STATUS0 = 0x87,
+    FM_FT_CON9 = 0x8F,
+       FM_DSP_PATCH_CTRL = 0x90,
+       FM_DSP_PATCH_OFFSET = 0x91,
+       FM_DSP_PATCH_DATA = 0x92,
+       FM_DSP_MEM_CTRL4 = 0x93,
+       FM_ADDR_PAMD = 0xB4,
+       FM_RDS_BDGRP_ABD_CTRL_REG = 0xB6,
+       FM_RDS_POINTER = 0xF0,   
+};
+
+//RDS_BDGRP_ABD_CTRL_REG
+enum{
+       BDGRP_ABD_EN = 0x0001,
+       BER_RUN = 0x2000
+};
+#define FM_DAC_CON1 0x83
+#define FM_DAC_CON2 0x84
+#define FM_FT_CON0 0x86
+enum{
+       FT_EN = 0x0001
+};
+          
+#define FM_I2S_CON0 0x90
+enum{
+       I2S_EN = 0x0001,
+       FORMAT = 0x0002,
+       WLEN = 0x0004,
+       I2S_SRC = 0x0008
+};
+
+//FM_MAIN_CTRL
+enum{
+       TUNE = 0x0001,
+       SEEK = 0x0002,
+       SCAN = 0x0004,
+       RDS_MASK = 0x0010,
+       MUTE = 0x0020,
+       RDS_BRST = 0x0040,
+       RAMP_DOWN = 0x0100,
+};
+
+//FM_MAIN_INTR
+enum{
+       FM_INTR_STC_DONE = 0x0001,
+       FM_INTR_IQCAL_DONE = 0x0002,                            
+       FM_INTR_DESENSE_HIT     = 0x0004,                               
+       FM_INTR_CHNL_CHG = 0x0008,                              
+       FM_INTR_SW_INTR = 0x0010,       
+       FM_INTR_RDS = 0x0020
+};
+
+enum{
+       ANTENNA_TYPE = 0x0010,
+};
+
+#endif //__MT6626_FM_REG_H__
+
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6626/piv/mt6626_fm_priv.c b/drivers/mtk_wcn_combo/drv_fm/mt6626/piv/mt6626_fm_priv.c
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6626/piv/mt6626_fm_priv.h b/drivers/mtk_wcn_combo/drv_fm/mt6626/piv/mt6626_fm_priv.h
new file mode 100755 (executable)
index 0000000..8a94e41
--- /dev/null
@@ -0,0 +1,5 @@
+#ifndef __MTK_FM_H__
+#define __MTK_FM_H__
+
+
+#endif //__MTK_FM_H__
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6626/pub/mt6626_fm_cmd.c b/drivers/mtk_wcn_combo/drv_fm/mt6626/pub/mt6626_fm_cmd.c
new file mode 100755 (executable)
index 0000000..67156d1
--- /dev/null
@@ -0,0 +1,672 @@
+#include <linux/kernel.h>
+
+#include "fm_typedef.h"
+#include "fm_dbg.h"
+#include "fm_err.h"
+#include "fm_rds.h"
+#include "fm_cust_cfg.h"
+
+#include "mt6626_fm_reg.h"
+#include "mt6626_fm_link.h"
+#include "mt6626_fm.h"
+#include "mt6626_fm_cmd.h"
+
+static fm_s32 fm_bop_write(fm_u8 addr, fm_u16 value, fm_u8 *buf, fm_s32 size)
+{
+    if (size < (FM_WRITE_BASIC_OP_SIZE + 2)) {
+        return (-1);
+    }
+
+    if (buf == NULL) {
+        return (-2);
+    }
+
+    buf[0] = FM_WRITE_BASIC_OP;
+    buf[1] = FM_WRITE_BASIC_OP_SIZE;
+    buf[2] = addr;
+    buf[3] = (fm_u8)((value) & 0x00FF);
+    buf[4] = (fm_u8)((value >> 8) & 0x00FF);
+
+    WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4]);
+
+    return (FM_WRITE_BASIC_OP_SIZE + 2);
+}
+
+static fm_s32 fm_bop_udelay(fm_u32 value, fm_u8 *buf, fm_s32 size)
+{
+    if (size < (FM_UDELAY_BASIC_OP_SIZE + 2)) {
+        return (-1);
+    }
+
+    if (buf == NULL) {
+        return (-2);
+    }
+
+    buf[0] = FM_UDELAY_BASIC_OP;
+    buf[1] = FM_UDELAY_BASIC_OP_SIZE;
+    buf[2] = (fm_u8)((value) & 0x000000FF);
+    buf[3] = (fm_u8)((value >> 8) & 0x000000FF);
+    buf[4] = (fm_u8)((value >> 16) & 0x000000FF);
+    buf[5] = (fm_u8)((value >> 24) & 0x000000FF);
+
+    WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
+
+    return (FM_UDELAY_BASIC_OP_SIZE + 2);
+}
+
+static fm_s32 fm_bop_rd_until(fm_u8 addr, fm_u16 mask, fm_u16 value, fm_u8 *buf, fm_s32 size)
+{
+    if (size < (FM_RD_UNTIL_BASIC_OP_SIZE + 2)) {
+        return (-1);
+    }
+
+    if (buf == NULL) {
+        return (-2);
+    }
+
+    buf[0] = FM_RD_UNTIL_BASIC_OP;
+    buf[1] = FM_RD_UNTIL_BASIC_OP_SIZE;
+    buf[2] = addr;
+    buf[3] = (fm_u8)((mask) & 0x00FF);
+    buf[4] = (fm_u8)((mask >> 8) & 0x00FF);
+    buf[5] = (fm_u8)((value) & 0x00FF);
+    buf[6] = (fm_u8)((value >> 8) & 0x00FF);
+
+    WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
+
+    return (FM_RD_UNTIL_BASIC_OP_SIZE + 2);
+}
+
+static fm_s32 fm_bop_modify(fm_u8 addr, fm_u16 mask_and, fm_u16 mask_or, fm_u8 *buf, fm_s32 size)
+{
+    if (size < (FM_MODIFY_BASIC_OP_SIZE + 2)) {
+        return (-1);
+    }
+
+    if (buf == NULL) {
+        return (-2);
+    }
+
+    buf[0] = FM_MODIFY_BASIC_OP;
+    buf[1] = FM_MODIFY_BASIC_OP_SIZE;
+    buf[2] = addr;
+    buf[3] = (fm_u8)((mask_and) & 0x00FF);
+    buf[4] = (fm_u8)((mask_and >> 8) & 0x00FF);
+    buf[5] = (fm_u8)((mask_or) & 0x00FF);
+    buf[6] = (fm_u8)((mask_or >> 8) & 0x00FF);
+
+    WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
+
+    return (FM_MODIFY_BASIC_OP_SIZE + 2);
+}
+
+#if 0
+static fm_s32 fm_bop_msleep(fm_u32 value, fm_u8 *buf, fm_s32 size)
+{
+    if (size < (FM_MSLEEP_BASIC_OP_SIZE + 2)) {
+        return (-1);
+    }
+
+    if (buf == NULL) {
+        return (-2);
+    }
+
+    buf[0] = FM_MSLEEP_BASIC_OP;
+    buf[1] = FM_MSLEEP_BASIC_OP_SIZE;
+    buf[2] = (fm_u8)((value) & 0x000000FF);
+    buf[3] = (fm_u8)((value >> 8) & 0x000000FF);
+    buf[4] = (fm_u8)((value >> 16) & 0x000000FF);
+    buf[5] = (fm_u8)((value >> 24) & 0x000000FF);
+
+    WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
+
+    return (FM_MSLEEP_BASIC_OP_SIZE + 2);
+}
+#endif
+
+/*
+ * mt6626_pwrup_clock_on - Wholechip FM Power Up: step 1, FM Digital Clock enable
+ * @buf - target buf
+ * @buf_size - buffer size
+ * return package size
+ */
+fm_s32 mt6626_pwrup_clock_on(fm_u8 *buf, fm_s32 buf_size)
+{
+    fm_s32 pkt_size = 0;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_ENABLE_OPCODE;
+    pkt_size = 4;
+
+    //FM Digital Clock enable
+    pkt_size += fm_bop_write(0x60, 0x3000, &buf[pkt_size], buf_size - pkt_size);//wr 60 3000
+    pkt_size += fm_bop_write(0x60, 0x3001, &buf[pkt_size], buf_size - pkt_size);//wr 60 3001
+    pkt_size += fm_bop_udelay(3000, &buf[pkt_size], buf_size - pkt_size);//delay 3ms
+    pkt_size += fm_bop_write(0x60, 0x3003, &buf[pkt_size], buf_size - pkt_size);//wr 60 3003
+    pkt_size += fm_bop_write(0x60, 0x3007, &buf[pkt_size], buf_size - pkt_size);//wr 60 3007
+    //no low power mode, analog line in, long antenna
+    pkt_size += fm_bop_modify(0x61, 0xFF63, 0x0000, &buf[pkt_size], buf_size - pkt_size);
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+/*
+ * mt6626_patch_download - Wholechip FM Power Up: step 3, download patch to f/w,
+ * @buf - target buf
+ * @buf_size - buffer size
+ * @seg_num - total segments that this patch divided into
+ * @seg_id - No. of Segments: segment that will now be sent
+ * @src - patch source buffer
+ * @seg_len - segment size: segment that will now be sent
+ * return package size
+ */
+fm_s32 mt6626_patch_download(fm_u8 *buf, fm_s32 buf_size, fm_u8 seg_num, fm_u8 seg_id, const fm_u8 *src, fm_s32 seg_len)
+{
+    fm_s32 pkt_size = 0;
+    fm_u8 *dst = NULL;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_PATCH_DOWNLOAD_OPCODE;
+    pkt_size = 4;
+
+    buf[pkt_size++] = seg_num;
+    buf[pkt_size++] = seg_id;
+
+    if (seg_len > (buf_size - pkt_size)) {
+        return -1;
+    }
+
+    dst = &buf[pkt_size];
+    pkt_size += seg_len;
+
+    //copy patch to tx buffer
+    while (seg_len--) {
+        *dst = *src;
+        //printk(KERN_ALERT "%02x ", *dst);
+        src++;
+        dst++;
+    }
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+    WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
+
+    return pkt_size;
+}
+
+/*
+ * mt6626_coeff_download - Wholechip FM Power Up: step 3,download coeff to f/w,
+ * @buf - target buf
+ * @buf_size - buffer size
+ * @seg_num - total segments that this patch divided into
+ * @seg_id - No. of Segments: segment that will now be sent
+ * @src - patch source buffer
+ * @seg_len - segment size: segment that will now be sent
+ * return package size
+ */
+fm_s32 mt6626_coeff_download(fm_u8 *buf, fm_s32 buf_size, fm_u8 seg_num, fm_u8 seg_id, const fm_u8 *src, fm_s32 seg_len)
+{
+    fm_s32 pkt_size = 0;
+    fm_u8 *dst = NULL;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_COEFF_DOWNLOAD_OPCODE;
+    pkt_size = 4;
+
+    buf[pkt_size++] = seg_num;
+    buf[pkt_size++] = seg_id;
+
+    if (seg_len > (buf_size - pkt_size)) {
+        return -1;
+    }
+
+    dst = &buf[pkt_size];
+    pkt_size += seg_len;
+
+    //copy patch to tx buffer
+    while (seg_len--) {
+        *dst = *src;
+        //printk(KERN_ALERT "%02x ", *dst);
+        src++;
+        dst++;
+    }
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+    WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
+
+    return pkt_size;
+}
+
+/*
+ * mt6626_hwcoeff_download - Wholechip FM Power Up: step 3,download hwcoeff to f/w,
+ * @buf - target buf
+ * @buf_size - buffer size
+ * @seg_num - total segments that this patch divided into
+ * @seg_id - No. of Segments: segment that will now be sent
+ * @src - patch source buffer
+ * @seg_len - segment size: segment that will now be sent
+ * return package size
+ */
+fm_s32 mt6626_hwcoeff_download(fm_u8 *buf, fm_s32 buf_size, fm_u8 seg_num, fm_u8 seg_id, const fm_u8 *src, fm_s32 seg_len)
+{
+    fm_s32 pkt_size = 0;
+    fm_u8 *dst = NULL;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_HWCOEFF_DOWNLOAD_OPCODE;
+    pkt_size = 4;
+
+    buf[pkt_size++] = seg_num;
+    buf[pkt_size++] = seg_id;
+
+    if (seg_len > (buf_size - pkt_size)) {
+        return -1;
+    }
+
+    dst = &buf[pkt_size];
+    pkt_size += seg_len;
+
+    //copy patch to tx buffer
+    while (seg_len--) {
+        *dst = *src;
+        //printk(KERN_ALERT "%02x ", *dst);
+        src++;
+        dst++;
+    }
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+    WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
+
+    return pkt_size;
+}
+
+/*
+ * mt6626_rom_download - Wholechip FM Power Up: step 3,download rom to f/w,
+ * @buf - target buf
+ * @buf_size - buffer size
+ * @seg_num - total segments that this patch divided into
+ * @seg_id - No. of Segments: segment that will now be sent
+ * @src - patch source buffer
+ * @seg_len - segment size: segment that will now be sent
+ * return package size
+ */
+fm_s32 mt6626_rom_download(fm_u8 *buf, fm_s32 buf_size, fm_u8 seg_num, fm_u8 seg_id, const fm_u8 *src, fm_s32 seg_len)
+{
+    fm_s32 pkt_size = 0;
+    fm_u8 *dst = NULL;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_ROM_DOWNLOAD_OPCODE;
+    pkt_size = 4;
+
+    buf[pkt_size++] = seg_num;
+    buf[pkt_size++] = seg_id;
+
+    if (seg_len > (buf_size - pkt_size)) {
+        return -1;
+    }
+
+    dst = &buf[pkt_size];
+    pkt_size += seg_len;
+
+    //copy patch to tx buffer
+    while (seg_len--) {
+        *dst = *src;
+        //printk(KERN_ALERT "%02x ", *dst);
+        src++;
+        dst++;
+    }
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+    WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
+
+    return pkt_size;
+}
+
+/*
+ * mt6626_pwrup_digital_init - Wholechip FM Power Up: step 4, FM Digital Init: fm_rgf_maincon
+ * @buf - target buf
+ * @buf_size - buffer size
+ * return package size
+ */
+fm_s32 mt6626_pwrup_digital_init_1(fm_u8 *buf, fm_s32 buf_size)
+{
+    fm_s32 pkt_size = 0;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_ENABLE_OPCODE;
+    pkt_size = 4;
+
+    //Wholechip FM Power Up: FM Digital Init: fm_rgf_maincon
+    pkt_size += fm_bop_write(0x6A, 0x0020, &buf[pkt_size], buf_size - pkt_size);//wr 6A 0020
+    pkt_size += fm_bop_write(0x6B, 0x0020, &buf[pkt_size], buf_size - pkt_size);//wr 6B 0020
+    pkt_size += fm_bop_write(0xA0, 0xD0B1, &buf[pkt_size], buf_size - pkt_size);//wr a0 D0B1
+    pkt_size += fm_bop_write(0x60, 0x300F, &buf[pkt_size], buf_size - pkt_size);//wr 60 300F
+    pkt_size += fm_bop_write(0x61, 0x0003, &buf[pkt_size], buf_size - pkt_size);//wr 61 3
+    pkt_size += fm_bop_write(0x61, 0x0002, &buf[pkt_size], buf_size - pkt_size);//wr 61 2
+    //pkt_size += fm_bop_modify(0x61, 0xFFFF, 0x0002, &buf[pkt_size], buf_size - pkt_size);
+    //pkt_size += fm_bop_modify(0x61, 0xFFFE, 0x0000, &buf[pkt_size], buf_size - pkt_size);
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+/*
+ * mt6626_pwrup_digital_init - Wholechip FM Power Up: step 4, FM Digital Init: fm_rgf_maincon
+ * @buf - target buf
+ * @buf_size - buffer size
+ * return package size
+ */
+fm_s32 mt6626_pwrup_digital_init_2(fm_u8 *buf, fm_s32 buf_size)
+{
+    fm_s32 pkt_size = 0;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_ENABLE_OPCODE;
+    pkt_size = 4;
+
+    pkt_size += fm_bop_rd_until(0x64, 0x001F, 0x0002, &buf[pkt_size], buf_size - pkt_size);//Poll 64[0~4] = 2
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+/*
+ * mt6626_pwrdown - Wholechip FM Power down: Digital Modem Power Down
+ * @buf - target buf
+ * @buf_size - buffer size
+ * return package size
+ */
+fm_s32 mt6626_pwrdown(fm_u8 *buf, fm_s32 buf_size)
+{
+    fm_s32 pkt_size = 0;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_ENABLE_OPCODE;
+    pkt_size = 4;
+
+    //Disable HW clock control
+    pkt_size += fm_bop_write(0x60, 0x330F, &buf[pkt_size], buf_size - pkt_size);//wr 60 330F
+    //Reset ASIP
+    pkt_size += fm_bop_write(0x61, 0x0001, &buf[pkt_size], buf_size - pkt_size);//wr 61 0001
+    //digital core + digital rgf reset
+    pkt_size += fm_bop_modify(0x6E, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 6E[0~2] 0
+    pkt_size += fm_bop_modify(0x6E, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 6E[0~2] 0
+    pkt_size += fm_bop_modify(0x6E, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 6E[0~2] 0
+    //Disable all clock
+    pkt_size += fm_bop_write(0x60, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 60 0000
+    //Reset rgfrf
+    pkt_size += fm_bop_write(0x60, 0x4000, &buf[pkt_size], buf_size - pkt_size);//wr 60 4000
+    pkt_size += fm_bop_write(0x60, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 60 0000
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+/*
+ * mt6626_rampdown - f/w will wait for STC_DONE interrupt
+ * @buf - target buf
+ * @buf_size - buffer size
+ * return package size
+ */
+fm_s32 mt6626_rampdown(fm_u8 *buf, fm_s32 buf_size)
+{
+    fm_s32 pkt_size = 0;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_RAMPDOWN_OPCODE;
+    pkt_size = 4;
+
+    //Clear DSP state
+    pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFF0, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 63[3:0] = 0
+    //Set DSP ramp down state
+    pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFFF, RAMP_DOWN, &buf[pkt_size], buf_size - pkt_size);//wr 63[8] = 1
+    //@Wait for STC_DONE interrupt@
+    pkt_size += fm_bop_rd_until(FM_MAIN_INTR, FM_INTR_STC_DONE, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//Poll 69[0] = b'1
+    //Clear DSP ramp down state
+    pkt_size += fm_bop_modify(FM_MAIN_CTRL, (~RAMP_DOWN), 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 63[8] = 0
+    //Write 1 clear the STC_DONE interrupt status flag
+    pkt_size += fm_bop_modify(FM_MAIN_INTR, 0xFFFF, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//wr 69[0] = 1
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+/*
+ * mt6626_tune - execute tune action,
+ * @buf - target buf
+ * @buf_size - buffer size
+ * @freq - 760 ~ 1080, 100KHz unit
+ * return package size
+ */
+fm_s32 mt6626_tune(fm_u8 *buf, fm_s32 buf_size, fm_u16 freq)
+{
+    fm_s32 pkt_size = 0;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    freq = (freq - 640) * 2;
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_TUNE_OPCODE;
+    pkt_size = 4;
+
+    //Set desired channel & channel parameter
+    pkt_size += fm_bop_modify(FM_CHANNEL_SET, 0xFC00, freq, &buf[pkt_size], buf_size - pkt_size);// set 0x65[9:0] = 0x029e, => ((97.5 - 64) * 20)
+    //Enable hardware controlled tuning sequence
+    pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFFE, TUNE, &buf[pkt_size], buf_size - pkt_size);// set 0x63[0] = 1
+    //Wait for STC_DONE interrupt
+    pkt_size += fm_bop_rd_until(FM_MAIN_INTR, FM_INTR_STC_DONE, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//Poll 69[0] = b'1
+    //Write 1 clear the STC_DONE interrupt status flag
+    pkt_size += fm_bop_modify(FM_MAIN_INTR, 0xFFFF, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//wr 69[0] = 1
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+/*
+ * mt6626_seek - execute seek action,
+ * @buf - target buf
+ * @buf_size - buffer size
+ * @seekdir - 0=seek up, 1=seek down
+ * @space - step, 50KHz:001, 100KHz:010, 200KHz:100
+ * @max_freq - upper bound
+ * @min_freq - lower bound
+ * return package size
+ */
+fm_s32 mt6626_seek(fm_u8 *buf, fm_s32 buf_size, fm_u16 seekdir, fm_u16 space, fm_u16 max_freq, fm_u16 min_freq)
+{
+    fm_s32 pkt_size = 0;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_SEEK_OPCODE;
+    pkt_size = 4;
+
+    //Program seek direction
+    if (seekdir == 0) {
+        pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xFBFF, 0x0000, &buf[pkt_size], buf_size - pkt_size);//0x66[10] = 0, seek up
+    } else {
+        pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xFFFF, 0x0400, &buf[pkt_size], buf_size - pkt_size);//0x66[10] = 1, seek down
+    }
+
+    //Program scan channel spacing
+    if (space == 1) {
+        pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0x8FFF, 0x1000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=001
+    } else if (space == 2) {
+        pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0x8FFF, 0x2000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=010
+    } else if (space == 4) {
+        pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0x8FFF, 0x4000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=100
+    }
+
+    //enable wrap , if it is not auto scan function, 0x66[11] 0=no wrarp, 1=wrap
+    pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xFFFF, 0x0800, &buf[pkt_size], buf_size - pkt_size);//0x66[11] = 1, wrap
+    //0x66[9:0] freq upper bound
+    max_freq = (max_freq - 640) * 2;
+    pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xFC00, max_freq, &buf[pkt_size], buf_size - pkt_size);
+    //0x67[9:0] freq lower bound
+    min_freq = (min_freq - 640) * 2;
+    pkt_size += fm_bop_modify(FM_MAIN_CFG2, 0xFC00, min_freq, &buf[pkt_size], buf_size - pkt_size);
+    //Enable hardware controlled seeking sequence
+    pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFFF, SEEK, &buf[pkt_size], buf_size - pkt_size);//0x63[1] = 1
+    //Wait for STC_DONE interrupt
+    pkt_size += fm_bop_rd_until(FM_MAIN_INTR, FM_INTR_STC_DONE, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//Poll 69[0] = b'1
+    //Write 1 clear the STC_DONE interrupt status flag
+    pkt_size += fm_bop_modify(FM_MAIN_INTR, 0xFFFF, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//wr 69[0] = 1
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+/*
+ * mt6626_scan - execute scan action,
+ * @buf - target buf
+ * @buf_size - buffer size
+ * @scandir - 0=seek up, 1=seek down
+ * @space - step, 50KHz:001, 100KHz:010, 200KHz:100
+ * @max_freq - upper bound
+ * @min_freq - lower bound
+ * return package size
+ */
+fm_s32 mt6626_scan(fm_u8 *buf, fm_s32 buf_size, fm_u16 scandir, fm_u16 space, fm_u16 max_freq, fm_u16 min_freq)
+{
+    fm_s32 pkt_size = 0;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_SCAN_OPCODE;
+    pkt_size = 4;
+
+    //Program seek direction
+    if (scandir == 0) {
+        pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xFBFF, 0x0000, &buf[pkt_size], buf_size - pkt_size);//0x66[10] = 0, seek up
+    } else {
+        pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xFFFF, 0x0400, &buf[pkt_size], buf_size - pkt_size);//0x66[10] = 1, seek down
+    }
+
+    //Program scan channel spacing
+    if (space == 1) {
+        pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0x8FFF, 0x1000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=001
+    } else if (space == 2) {
+        pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0x8FFF, 0x2000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=010
+    } else if (space == 4) {
+        pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0x8FFF, 0x4000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=100
+    }
+
+    //disable wrap , if it is auto scan function, 0x66[11] 0=no wrarp, 1=wrap
+    pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xF7FF, 0x0000, &buf[pkt_size], buf_size - pkt_size);//0x66[11] = 0, no wrap
+    //0x66[9:0] freq upper bound
+    max_freq = (max_freq - 640) * 2;
+    pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xFC00, max_freq, &buf[pkt_size], buf_size - pkt_size);
+    //0x67[9:0] freq lower bound
+    min_freq = (min_freq - 640) * 2;
+    pkt_size += fm_bop_modify(FM_MAIN_CFG2, 0xFC00, min_freq, &buf[pkt_size], buf_size - pkt_size);
+    //Enable hardware controlled scanning sequence
+    pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFFF, SCAN, &buf[pkt_size], buf_size - pkt_size);//0x63[1] = 1
+    //Wait for STC_DONE interrupt
+    pkt_size += fm_bop_rd_until(FM_MAIN_INTR, FM_INTR_STC_DONE, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//Poll 69[0] = b'1
+    //Write 1 clear the STC_DONE interrupt status flag
+    pkt_size += fm_bop_modify(FM_MAIN_INTR, 0xFFFF, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//wr 69[0] = 1
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+fm_s32 mt6626_get_reg(fm_u8 *buf, fm_s32 buf_size, fm_u8 addr)
+{
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FSPI_READ_OPCODE;
+    buf[2] = 0x01;
+    buf[3] = 0x00;
+    buf[4] = addr;
+
+    WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4]);
+    return 5;
+}
+
+fm_s32 mt6626_set_reg(fm_u8 *buf, fm_s32 buf_size, fm_u8 addr, fm_u16 value)
+{
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FSPI_WRITE_OPCODE;
+    buf[2] = 0x03;
+    buf[3] = 0x00;
+    buf[4] = addr;
+    buf[5] = (fm_u8)((value) & 0x00FF);
+    buf[6] = (fm_u8)((value >> 8) & 0x00FF);
+
+    WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
+    return 7;
+}
+
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6626/pub/mt6626_fm_eint.c b/drivers/mtk_wcn_combo/drv_fm/mt6626/pub/mt6626_fm_eint.c
new file mode 100755 (executable)
index 0000000..046519c
--- /dev/null
@@ -0,0 +1,135 @@
+/* mt6626_fm_eint.c
+ *
+ * (C) Copyright 2009
+ * MediaTek <www.MediaTek.com>
+ * Hongcheng <hongcheng.xia@MediaTek.com>
+ *
+ * mt6626 FM Radio Driver -- EINT functions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include "fm_typedef.h"
+#include "fm_dbg.h"
+#include "fm_err.h"
+#include "fm_eint.h"
+
+#ifdef MT6516
+#include <mach/mt6516_eint.h>
+#include <mach/mt6516_gpio.h>
+#endif
+#ifdef MT6573
+#include <mach/mt6573_eint.h>
+#include <mach/mt6573_gpio.h>
+#endif
+#ifdef MT6575
+#include <mach/eint.h>
+#include <mach/mt6575_gpio.h>
+#endif
+
+#include <cust_eint.h>
+#include <cust_gpio_usage.h>
+
+struct fm_eint_interface {
+    void (*mask)(fm_u32 eint_num);
+    void (*unmask)(fm_u32 eint_num);
+    void (*set_hw_debounce)(fm_u32 eint_num, fm_u32 ms);
+    void (*set_polarity)(fm_u32 eint_num, fm_u32 pol);
+    fm_u32(*set_sens)(fm_u32 eint_num, fm_u32 sens);
+    void (*registration)(fm_u32 eint_num, fm_u32 is_deb_en, fm_u32 pol, void (EINT_FUNC_PTR)(void), fm_u32 is_auto_umask);
+    fm_s32(*init)(void);
+};
+
+
+#ifdef MT6516
+extern void MT6516_EINTIRQUnmask(fm_u32 line);
+extern void MT6516_EINTIRQMask(fm_u32 line);
+extern void MT6516_EINT_Set_HW_Debounce(fm_u8 eintno, fm_u32 ms);
+extern fm_u32 MT6516_EINT_Set_Sensitivity(fm_u8 eintno, kal_bool sens);
+extern void MT6516_EINT_Registration(fm_u8 eintno, kal_bool Dbounce_En,
+                                     kal_bool ACT_Polarity, void (EINT_FUNC_PTR)(void),
+                                     kal_bool auto_umask);
+#endif
+
+static struct fm_eint_interface fm_eint_ops = {
+#ifdef MT6516
+    .mask = MT6516_EINTIRQMask,
+    .unmask = MT6516_EINTIRQUnmask,
+    .set_hw_debounce = MT6516_EINT_Set_HW_Debounce,
+    .set_polarity = NULL,
+    .set_sens = MT6516_EINT_Set_Sensitivity,
+    .registration = MT6516_EINT_Registration,
+    .init = NULL,
+#else
+    .mask = mt65xx_eint_mask,
+    .unmask = mt65xx_eint_unmask,
+    .set_hw_debounce = mt65xx_eint_set_hw_debounce,
+    .set_polarity = mt65xx_eint_set_polarity,
+    .set_sens = mt65xx_eint_set_sens,
+    .registration = mt65xx_eint_registration,
+    .init = mt65xx_eint_init,
+#endif
+};
+fm_s32 fm_enable_eint(void)
+{
+    WCN_DBG(FM_INF | EINT, "%s\n", __func__);
+    fm_eint_ops.unmask(CUST_EINT_FM_RDS_NUM);
+    return 0;
+}
+
+fm_s32 fm_disable_eint(void)
+{
+    WCN_DBG(FM_INF | EINT, "%s\n", __func__);
+    fm_eint_ops.mask(CUST_EINT_FM_RDS_NUM);
+    return 0;
+}
+
+fm_s32 fm_request_eint(void (*parser)(void))
+{
+    WCN_DBG(FM_NTC | EINT, "%s\n", __func__);
+    fm_eint_ops.set_sens(CUST_EINT_FM_RDS_NUM, CUST_EINT_FM_RDS_SENSITIVE);
+    fm_eint_ops.set_hw_debounce(CUST_EINT_FM_RDS_NUM, CUST_EINT_FM_RDS_DEBOUNCE_CN);
+    fm_eint_ops.registration(CUST_EINT_FM_RDS_NUM,
+                             CUST_EINT_FM_RDS_DEBOUNCE_EN,
+                             CUST_EINT_FM_RDS_POLARITY,
+                             parser,
+                             0);
+    fm_eint_ops.mask(CUST_EINT_FM_RDS_NUM);
+    return 0;
+}
+
+fm_s32 fm_eint_pin_cfg(fm_s32 mode)
+{
+    int ret = 0;
+
+    WCN_DBG(FM_NTC | EINT, "%s\n", __func__);
+
+    switch (mode) {
+    case FM_EINT_PIN_EINT_MODE:
+        mt_set_gpio_mode(GPIO_FM_RDS_PIN, GPIO_FM_RDS_PIN_M_GPIO);
+        mt_set_gpio_pull_enable(GPIO_FM_RDS_PIN, GPIO_PULL_ENABLE);
+        mt_set_gpio_pull_select(GPIO_FM_RDS_PIN, GPIO_PULL_UP);
+        mt_set_gpio_mode(GPIO_FM_RDS_PIN, GPIO_FM_RDS_PIN_M_EINT);
+        break;
+    case FM_EINT_PIN_GPIO_MODE:
+        mt_set_gpio_mode(GPIO_FM_RDS_PIN, GPIO_FM_RDS_PIN_M_GPIO);
+        mt_set_gpio_dir(GPIO_FM_RDS_PIN, GPIO_DIR_IN);
+        break;
+    default:
+        ret = -1;
+        break;
+    }
+
+    return ret;
+}
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6626/pub/mt6626_fm_lib.c b/drivers/mtk_wcn_combo/drv_fm/mt6626/pub/mt6626_fm_lib.c
new file mode 100755 (executable)
index 0000000..2b7c5d4
--- /dev/null
@@ -0,0 +1,1147 @@
+#include <linux/semaphore.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+
+#include "fm_typedef.h"
+#include "fm_dbg.h"
+#include "fm_err.h"
+#include "fm_interface.h"
+#include "fm_stdlib.h"
+#include "fm_patch.h"
+#include "fm_config.h"
+
+#include "mt6626_fm_reg.h"
+#include "mt6626_fm.h"
+#include "mt6626_drv_dsp.h"
+#include "mt6626_fm_link.h"
+#include "mt6626_fm_lib.h"
+#include "mt6626_fm_cmd.h"
+
+#define MT6626_FM_PATCH_PATH "/etc/firmware/mt6626_fm_patch.bin"
+#define MT6626_FM_COEFF_PATH "/etc/firmware/mt6626_fm_coeff.bin"
+#define MT6626_FM_HWCOEFF_PATH "/etc/firmware/mt6626_fm_hwcoeff.bin"
+#define MT6626_FM_ROM_PATH "/etc/firmware/mt6626_fm_rom.bin"
+
+extern void fm_low_power_wa(int fmon);
+extern void mt66x6_poweron(int idx);
+extern void mt66x6_poweroff(int idx);
+
+static struct fm_callback *fm_cb_op;
+
+/* mt6626 FM Receiver Power Up Sequence*/
+static const struct ctrl_word_operation PowerOnSetting[] = {
+    //@Wholechip FM Power Up: FM Digital Clock enable
+    {0x60, 0x0, 0x3000},
+    {0x60, 0x0, 0x3001},
+    {MSDELAY, 0x0, 0x0003},//Delay 3ms
+    {0x60, 0x0, 0x3003},
+    {0x60, 0x0, 0x3007},
+    {HW_VER, 0x99, 0x0000},
+    //antenna and audio path config
+#ifdef FMRADIO_I2S_SUPPORT
+#ifdef FM_PowerOn_with_ShortAntenna
+    {0x61, 0xFF73, 0x0090},//no low power mode, I2S, short antenna
+#else
+    {0x61, 0xFF73, 0x0080},//no low power mode, I2S, long antenna
+#endif
+    {0x9B, 0xFFF7, 0x0008},//0000->master, 0008->slave
+    {0x5F, 0xE7FF, 0x0000},//0000->32K, 0800->44.1K, 1000->48K
+    //{0x61, 0xFF73, 0x0080},//no low power mode, I2S, long antenna, 0xff63
+    //{0x9B, 0xFFF7, 0x0008},//0000->master, 0008->slave
+    //{0x5F, 0xE7FF, 0x0000},//0000->32K, 0800->44.1K, 1000->48K
+#else
+#ifdef FM_PowerOn_with_ShortAntenna
+    {0x61, 0xFF63, 0x0010},//no low power mode, analog line in, short antenna
+#else
+    {0x61, 0xFF63, 0x0000},//no low power mode, analog line in, long antenna
+#endif
+#endif
+    {HW_VER, 0x0062, 0x0000},//read the HW version
+
+    //@Wholechip FM Power Up: FM Digital Init: download patch/DSP coefficient/HWACC coefficient
+    {DSPPATCH, 0x0, DSP_PATH},
+    {DSPPATCH, 0x0, DSP_COEFF},
+    {DSPPATCH, 0x0, DSP_HW_COEFF},
+    {0x90, 0x0, 0x0040},
+    {0x90, 0x0, 0x0000},
+
+    //@Wholechip FM Power Up: FM Digital Init: fm_rgf_maincon
+    {0x6A, 0x0, 0x0020},
+    {0x6B, 0x0, 0x0020},
+    {0x60, 0x0, 0x300F},
+    {0x61, 0xFFFF, 0x0002},
+    {0x61, 0xFFFE, 0x0000},
+    {POLL_P, 0x64, 0x2}
+};
+#define POWER_ON_COMMAND_COUNT (sizeof(PowerOnSetting)/sizeof(PowerOnSetting[0]))
+
+static int Chip_Version = mt6626_E1;
+
+
+static fm_s32 mt6626_pwron(fm_s32 data)
+{
+    mt66x6_poweron(MT66x6_FM);
+    return 0;
+}
+
+
+static fm_s32 mt6626_pwroff(fm_s32 data)
+{
+    mt66x6_poweroff(MT66x6_FM);
+    return 0;
+}
+
+static fm_s32 Delayms(fm_u32 data)
+{
+    WCN_DBG(FM_DBG | CHIP, "delay %dms\n", data);
+    msleep(data);
+    return 0;
+}
+
+static fm_s32 Delayus(fm_u32 data)
+{
+    WCN_DBG(FM_DBG | CHIP, "delay %dus\n", data);
+    udelay(data);
+    return 0;
+}
+
+static fm_s32 mt6626_read(fm_u8 addr, fm_u16 *val)
+{
+    fm_s32 ret = 0;
+
+    ret = fm_ctrl_rx(addr, val);
+
+    if (ret) {
+        WCN_DBG(FM_ALT | CHIP, "rd 0x%02x err\n", addr);
+        return ret;
+    }
+
+    WCN_DBG(FM_DBG | CHIP, "rd 0x%02x 0x%04x\n", addr, *val);
+    return ret;
+}
+
+static fm_s32 mt6626_write(fm_u8 addr, fm_u16 val)
+{
+    fm_s32 ret = 0;
+
+    ret = fm_ctrl_tx(addr, val);
+
+    if (ret) {
+        WCN_DBG(FM_ALT | CHIP, "wr 0x%02x err\n", addr);
+        return ret;
+    }
+
+    WCN_DBG(FM_DBG | CHIP, "wr 0x%02x 0x%04x\n", addr, val);
+    return ret;
+}
+
+static fm_s32 mt6626_write1(fm_u8 addr, fm_u16 val)
+{
+    return fm_ctrl_tx(addr, val);
+}
+
+static fm_s32 mt6626_set_bits(fm_u8 addr, fm_u16 bits, fm_u16 mask)
+{
+    fm_s32 ret = 0;
+    fm_u16 val;
+
+    ret = mt6626_read(addr, &val);
+
+    if (ret)
+        return ret;
+
+    val = ((val & (mask)) | bits);
+    ret = mt6626_write(addr, val);
+
+    return ret;
+}
+
+static fm_u16 mt6626_get_chipid(void)
+{
+    return 0x6626;
+}
+
+static void mt6626_TUNE_ON(void)
+{
+    fm_u16 dataRead;
+
+    WCN_DBG(FM_DBG | CHIP, "tune on\n");
+    mt6626_read(FM_MAIN_CTRL, &dataRead);
+    //mt6626_write(FM_MAIN_CTRL, (dataRead&0xFFFE)|TUNE);
+    mt6626_write(FM_MAIN_CTRL, (dataRead&0xFFF8) | TUNE);
+}
+
+static void mt6626_SEEK_ON(void)
+{
+    fm_u16 dataRead;
+
+    WCN_DBG(FM_DBG | CHIP, "seek on\n");
+    mt6626_read(FM_MAIN_CTRL, &dataRead);
+    //mt6626_write(FM_MAIN_CTRL, (dataRead&0xFFFD)|SEEK);
+    mt6626_write(FM_MAIN_CTRL, (dataRead&0xFFF8) | SEEK);
+}
+
+static void mt6626_SCAN_ON(void)
+{
+    fm_u16 dataRead;
+
+    WCN_DBG(FM_DBG | CHIP, "scan on\n");
+    mt6626_read(FM_MAIN_CTRL, &dataRead);
+    //mt6626_write(FM_MAIN_CTRL, (dataRead&0xFFFB)|SCAN);
+    mt6626_write(FM_MAIN_CTRL, (dataRead&0xFFF8) | SCAN);
+}
+
+/*  MT6628_SetAntennaType - set Antenna type
+ *  @type - 1,Short Antenna;  0, Long Antenna
+ */
+static fm_s32 mt6626_SetAntennaType(fm_s32 type)
+{
+    fm_u16 dataRead;
+
+    WCN_DBG(FM_DBG | CHIP, "set ana to %s\n", type ? "short" : "long");
+    mt6626_read(FM_MAIN_CG2_CTRL, &dataRead);
+
+    if (type) {
+        dataRead |= ANTENNA_TYPE;
+    } else {
+        dataRead &= (~ANTENNA_TYPE);
+    }
+
+    mt6626_write(FM_MAIN_CG2_CTRL, dataRead);
+
+    return 0;
+}
+
+static fm_s32 mt6626_GetAntennaType(void)
+{
+    fm_u16 dataRead;
+
+    mt6626_read(FM_MAIN_CG2_CTRL, &dataRead);
+    WCN_DBG(FM_DBG | CHIP, "get ana type: %s\n", (dataRead&ANTENNA_TYPE) ? "short" : "long");
+
+    if (dataRead&ANTENNA_TYPE)
+        return FM_SHORT_ANA; //short antenna
+    else
+        return FM_LONG_ANA; //long antenna
+}
+
+static fm_s32 mt6626_writeFA(fm_u16 *buff, fm_u8 fa)
+{
+    fm_u8 i = 0;
+
+    for (i = 0; i < 3; i++) {
+        if ((fa >> i)& 0x1)
+            *buff |= (1 << (12 + i));
+        else
+            *buff &= ~(1 << (12 + i));
+    }
+
+    return 0;
+}
+
+static fm_s32 mt6626_Mute(fm_bool mute)
+{
+    fm_u16 dataRead;
+
+    WCN_DBG(FM_DBG | CHIP, "set %s\n", mute ? "mute" : "unmute");
+    mt6626_read(FM_MAIN_CTRL, &dataRead);
+
+    if (mute == 1) {
+        mt6626_write(FM_MAIN_CTRL, (dataRead&0xFFDF) | 0x0020);
+    } else {
+        mt6626_write(FM_MAIN_CTRL, (dataRead&0xFFDF));
+    }
+
+    return 0;
+}
+
+/*
+ * mt6626_WaitSTCDone - wait for stc done flag change to '1'
+ * @waittime - the total wait time in ms
+ * @interval - the delay time of every polling loop in ms
+ * if success, return 0; else error code
+ */
+static fm_s32 mt6626_WaitSTCDone(fm_u32 waittime, fm_u32 interval)
+{
+    fm_u16 dataRead;
+    fm_s32 cnt;
+
+    if (interval) {
+        cnt = waittime / interval;
+    } else {
+        cnt = 0;
+    }
+
+    do {
+        if (cnt-- < 0) {
+            return -1; //wait for STC done failed
+        }
+
+        Delayms(interval);
+        mt6626_read(FM_MAIN_INTR, &dataRead);
+    } while ((dataRead&FM_INTR_STC_DONE) == 0);
+
+    return 0;
+}
+
+static fm_s32 mt6626_ClearSTCDone(void)
+{
+    fm_u16 dataRead;
+
+    mt6626_read(FM_MAIN_INTR, &dataRead);
+    mt6626_write(FM_MAIN_INTR, dataRead | FM_INTR_STC_DONE);//clear status flag
+    return 0;
+}
+
+static fm_s32 mt6626_RampDown(void)
+{
+    fm_u16 dataRead;
+
+    WCN_DBG(FM_DBG | CHIP, "ramp down\n");
+    //Clear DSP state
+    mt6626_read(FM_MAIN_CTRL, &dataRead);
+    mt6626_write(FM_MAIN_CTRL, (dataRead&0xFFF0)); //clear rgf_tune/seek/scan/dsp_init
+
+    //Set DSP ramp down state
+    mt6626_read(FM_MAIN_CTRL, &dataRead);
+    mt6626_write(FM_MAIN_CTRL, (dataRead | RAMP_DOWN));
+
+    //Check STC_DONE status flag (not the interrupt flag!)
+    if (mt6626_WaitSTCDone(1000, 1)) {
+        WCN_DBG(FM_ALT | CHIP, "ramp down failed\n");
+        return -1;
+    }
+
+    //Clear DSP ramp down state
+    mt6626_read(FM_MAIN_CTRL, &dataRead);
+    mt6626_write(FM_MAIN_CTRL, (dataRead&(~RAMP_DOWN)));
+
+    mt6626_ClearSTCDone();
+    return 0;
+}
+
+/*
+*  mt6626_DspPatch - DSP download procedure
+*  @img - source dsp bin code
+*  @type - rom/patch/coefficient/hw_coefficient
+*
+*/
+static fm_s32 mt6626_DspPatch(const fm_u16 *img, enum IMG_TYPE type)
+{
+    fm_u32 ctrl_code = 0;
+    fm_u16 data_len = 0;       // in words
+    fm_u16 i;
+
+    FMR_ASSERT(img);
+
+    WCN_DBG(FM_DBG | CHIP, "down load DSP patch %d (1-rom, 2-patch, 3-coe, 4-hwcoe)\n", type);
+
+    switch (type) {
+    case IMG_ROM:                      //rom code
+    case IMG_PATCH:            //patch
+        ctrl_code = 0x10;
+        break;
+    case IMG_COEFFICIENT:      //coeff
+        ctrl_code = 0xe;
+        break;
+    case IMG_HW_COEFFICIENT:   //HW coeff
+        ctrl_code = 0xd;
+        break;
+    default:
+        break;
+    }
+
+    data_len = img[1] - img[0] + 1;
+    WCN_DBG(FM_DBG | CHIP, "patch len: %d\n", data_len);
+
+    if (!(data_len > 0)) {
+        ; //error
+        return -FM_EPARA;
+    }
+
+    mt6626_write(FM_DSP_PATCH_CTRL, 0);
+    mt6626_write(FM_DSP_PATCH_OFFSET, img[0]);         //Start address
+    mt6626_write(FM_DSP_PATCH_CTRL, 0x40);                     //Reset download control
+    mt6626_write(FM_DSP_PATCH_CTRL, ctrl_code);        //Set download control
+
+    switch (type) {
+    case IMG_ROM:
+    case IMG_PATCH:
+    case IMG_HW_COEFFICIENT:
+        WCN_DBG(FM_DBG | CHIP, "rom/patch/hw_coefficient downloading......\n");
+
+        for (i = 0; i < data_len; i++) {
+            mt6626_write1(FM_DSP_PATCH_DATA, img[2+i]);
+        }
+
+        break;
+    case IMG_COEFFICIENT:
+        WCN_DBG(FM_DBG | CHIP, "coefficient downloading......\n");
+
+        if (MT6626_DEEMPHASIS_50us) {
+            for (i = 0; i < data_len; i++) {
+                if (i == 86) {
+                    mt6626_write1(FM_DSP_PATCH_DATA, fm_cust_config_fetch(FM_CFG_RX_RSSI_TH_LONG));
+                } else if (i == 292) {
+                    mt6626_write1(FM_DSP_PATCH_DATA, 0x332B);
+                    mt6626_write1(FM_DSP_PATCH_DATA, 0x2545);
+                    mt6626_write1(FM_DSP_PATCH_DATA, 0x1344);
+                    mt6626_write1(FM_DSP_PATCH_DATA, 0x09F5);
+                    mt6626_write1(FM_DSP_PATCH_DATA, 0x0526);
+                    mt6626_write1(FM_DSP_PATCH_DATA, 0x02A9);
+                    mt6626_write1(FM_DSP_PATCH_DATA, 0x0160);
+                    mt6626_write1(FM_DSP_PATCH_DATA, 0x00B6);
+                    mt6626_write1(FM_DSP_PATCH_DATA, 0x005E);
+                    mt6626_write1(FM_DSP_PATCH_DATA, 0x0031);
+                    mt6626_write1(FM_DSP_PATCH_DATA, 0x0000);
+                    mt6626_write1(FM_DSP_PATCH_DATA, 0x0000);
+                    mt6626_write1(FM_DSP_PATCH_DATA, 0x0000);
+                    i += 12;
+                } else if (i == 505) {
+                    mt6626_write1(FM_DSP_PATCH_DATA, fm_cust_config_fetch(FM_CFG_RX_RSSI_TH_SHORT));
+                } else {
+                    mt6626_write1(FM_DSP_PATCH_DATA, img[2+i]);
+                }
+            }
+        } else {
+            for (i = 0; i < data_len; i++) {
+                if (i == 86) {
+                    mt6626_write1(FM_DSP_PATCH_DATA, fm_cust_config_fetch(FM_CFG_RX_RSSI_TH_LONG));
+                } else if (i == 505) {
+                    mt6626_write1(FM_DSP_PATCH_DATA, fm_cust_config_fetch(FM_CFG_RX_RSSI_TH_SHORT));
+                } else {
+                    mt6626_write1(FM_DSP_PATCH_DATA, img[2+i]);
+                }
+            }
+        }
+
+        break;
+    default:
+        break;
+    }
+
+    WCN_DBG(FM_DBG | CHIP, "down load DSP patch %d ok\n", type);
+    return 0;
+}
+
+static fm_s32 mt6626_PowerUp(fm_u16 *chip_id, fm_u16 *device_id)
+{
+    fm_s32 ret = 0;
+    fm_s32 i;
+    fm_u16 tmp_reg, cnt = 0;
+
+    const fm_u16 *bin_patch = NULL;
+    const fm_u16 *bin_coeff = NULL;
+
+    FMR_ASSERT(chip_id);
+    FMR_ASSERT(device_id);
+
+    WCN_DBG(FM_DBG | CHIP, "pwr on seq\n");
+
+    // mt6626 FM power on sequence
+    for (i = 0; i < POWER_ON_COMMAND_COUNT; i++) {
+        switch (PowerOnSetting[i].addr) {
+        case FM_PUS_DSPPATCH:
+
+            switch (PowerOnSetting[i].or) {
+            case DSP_PATH:  //DSP path download
+                mt6626_DspPatch(bin_patch, IMG_PATCH);
+                break;
+            case DSP_COEFF:  //DSP coefficient download
+                mt6626_DspPatch(bin_coeff, IMG_COEFFICIENT);
+                break;
+            case DSP_HW_COEFF:  //DSP HW coefficient download
+                mt6626_DspPatch(bin_hw_coeff, IMG_HW_COEFFICIENT);
+                break;
+            default:
+                break;
+            }
+
+            break;
+        case FM_PUS_POLL_P:
+            cnt = 0;
+
+            do {
+                mt6626_read((fm_u8)PowerOnSetting[i].and, &tmp_reg);
+                tmp_reg &= PowerOnSetting[i].or;
+
+                if (tmp_reg == 0) {
+                    Delayms(10);
+                    cnt++;
+                }
+            } while ((tmp_reg == 0) && (cnt < (MT6626_MAX_COUNT << 1)));
+
+            if (cnt == (MT6626_MAX_COUNT << 1)) {
+                WCN_DBG(FM_ALT | CHIP, "polling status Active failed:0x%02X\n", (fm_u8)PowerOnSetting[i].and);
+                return -FM_EPARA;
+            }
+
+            break;
+        case FM_PUS_POLL_N:
+            cnt = 0;
+
+            do {
+                mt6626_read((fm_u8)PowerOnSetting[i].and, &tmp_reg);
+                tmp_reg &= PowerOnSetting[i].or;
+
+                if (tmp_reg != 0) {
+                    Delayms(10);
+                    cnt++;
+                }
+            } while ((tmp_reg != 0) && (cnt < MT6626_MAX_COUNT));
+
+            if (cnt == MT6626_MAX_COUNT) {
+                WCN_DBG(FM_ALT | CHIP, "polling status Negative failed:0x%02X\n", (fm_u8)PowerOnSetting[i].and);
+                return -FM_EPARA;
+            }
+
+            break;
+        case FM_PUS_USDELAY:
+            Delayus(PowerOnSetting[i].or);
+            break;
+        case FM_PUS_MSDELAY:
+            Delayms(PowerOnSetting[i].or);
+            break;
+        case FM_PUS_HW_VER:
+
+            switch (PowerOnSetting[i].and) {
+            case 0x99:
+                mt6626_read(0x99, &tmp_reg);
+
+                switch (tmp_reg) {
+                case 0x0:
+                    Chip_Version = mt6626_E1;
+                    bin_patch = bin_patch_E1;
+                    bin_coeff = bin_coeff_E1;
+                    break;
+                case 0x8A01:
+                default:
+                    Chip_Version = mt6626_E2;
+                    bin_patch = bin_patch_E2;
+                    bin_coeff = bin_coeff_E2;
+                    break;
+                }
+
+                break;
+            case 0x62:
+                mt6626_read((fm_u8)PowerOnSetting[i].and, &tmp_reg);
+                //record chip id & device id
+                *chip_id = tmp_reg;
+                *device_id = tmp_reg;
+                WCN_DBG(FM_NTC | CHIP, "chip_id:0x%04x\n", tmp_reg);
+                break;
+            case 0x1C:
+                mt6626_read((fm_u8)PowerOnSetting[i].and, &tmp_reg);
+
+                if (PowerOnSetting[i].or) {
+                    mt6626_write(PowerOnSetting[i].and, (tmp_reg | 0x8000));
+                } else {
+                    mt6626_write(PowerOnSetting[i].and, (tmp_reg&0x7FFF));
+                }
+
+                break;
+            default:
+                break;
+            }
+
+            break;
+        default:
+
+            if (PowerOnSetting[i].and != 0) {
+                if (mt6626_read((fm_u8)PowerOnSetting[i].addr, &tmp_reg)) {
+                    WCN_DBG(FM_ALT | CHIP, "power up failed, can't read reg %02X\n", (fm_u8)PowerOnSetting[i].and);
+                    return -FM_EPARA;
+                }
+
+                tmp_reg &= PowerOnSetting[i].and;
+                tmp_reg |= PowerOnSetting[i].or;
+            } else {
+                tmp_reg = PowerOnSetting[i].or;
+            }
+
+            if (mt6626_write((fm_u8)PowerOnSetting[i].addr, tmp_reg)) {
+                WCN_DBG(FM_ALT | CHIP, "power up failed, can't write reg %02X\n", (fm_u8)PowerOnSetting[i].addr);
+                return -FM_EPARA;
+            }
+
+            break;
+        }
+    }
+
+    WCN_DBG(FM_DBG | CHIP, "pwr on seq done\n");
+    return ret;
+}
+
+static fm_s32 mt6626_PowerDown(void)
+{
+    fm_s32 ret = 0;
+    fm_s16 i;
+    fm_u16 dataRead;
+
+    /*SW work around for MCUFA issue.
+     *if interrupt happen before doing rampdown, DSP can't switch MCUFA back well.
+     * In case read interrupt, and clean if interrupt found before rampdown.
+     */
+    WCN_DBG(FM_DBG | CHIP, "pwr down seq\n");
+    mt6626_read(FM_MAIN_INTR, &dataRead);
+
+    if (dataRead & 0x1) {
+        mt6626_write(FM_MAIN_INTR, dataRead);//clear status flag
+    }
+
+    mt6626_RampDown();
+
+    mt6626_write(0x60, 0x330F);
+    mt6626_write(FM_MAIN_CG2_CTRL, 1);
+
+    for (i = 0; i < 4; i++) {
+        mt6626_read(0x6E, &dataRead);
+        mt6626_write(0x6E, (dataRead&0xFFF8));
+    }
+
+    mt6626_write(FM_MAIN_CG1_CTRL, 0);
+    mt6626_write(FM_MAIN_CG1_CTRL, 0x4000);
+    mt6626_write(FM_MAIN_CG1_CTRL, 0);
+
+    return ret;
+}
+
+static fm_bool mt6626_SetFreq(fm_u16 freq)
+{
+    fm_u32 CHAN = 0x0000;
+    fm_u16 dataRead, cnt = 0, tempbuff = 0;
+
+Rampdown_again:
+    mt6626_RampDown();
+
+    fm_cb_op->cur_freq_set(freq);
+    CHAN = (freq - 640) << 1;
+    mt6626_read(FM_CHANNEL_SET, &dataRead);
+
+    switch (Chip_Version) {
+    case mt6626_E1:
+
+        if (((fm_u8)((dataRead & 0x1000) >> 12)) ^(channel_parameter[freq - 760] & 0x1)) {
+            mt6626_read(0x61, &tempbuff);
+            mt6626_write(0x60, 0x330F);
+            mt6626_write(0x61, 1);
+            mt6626_write(0x6e, 0x0);
+            mt6626_write(0x6e, 0x0);
+            mt6626_write(0x6e, 0x0);
+            mt6626_write(0x6e, 0x0);
+            mt6626_write(0x60, 0x0);
+            mt6626_write(0x60, 0x4000);
+            mt6626_write(0x60, 0x0);
+            mt6626_write(0x60, 0x3000);
+            mt6626_write(0x60, 0x3001);
+            Delayms(3);
+            mt6626_write(0x60, 0x3003);
+            mt6626_write(0x60, 0x3007);
+            mt6626_write(0x60, 0x300f);
+            mt6626_write(0x61, tempbuff | 0x3);
+            mt6626_write(0x61, tempbuff | 0x2);
+            mt6626_write(0x6A, 0x20);
+            mt6626_write(0x6B, 0x20);
+            Delayms(200);
+        }
+
+        break;
+    case mt6626_E2:
+        break;
+    default:
+        break;
+
+    }
+
+    mt6626_writeFA(&dataRead, (channel_parameter[freq - 760]));
+    mt6626_write(FM_CHANNEL_SET, (dataRead&0xFC00) | CHAN);
+
+    mt6626_TUNE_ON();
+
+    if (mt6626_WaitSTCDone(5000, 15)) {
+        if (cnt++ > 100) {
+            WCN_DBG(FM_ALT | CHIP, "set freq failed\n");
+            return FALSE;
+        } else {
+            WCN_DBG(FM_WAR | CHIP, "set freq retry, cnt=%d\n", cnt);
+            goto Rampdown_again;
+        }
+    }
+
+    mt6626_ClearSTCDone();//clear status flag
+
+    WCN_DBG(FM_DBG | CHIP, "set freq to %d ok\n", freq);
+    return TRUE;
+}
+
+/*
+* mt6626_Seek
+* pFreq: IN/OUT parm, IN start freq/OUT seek valid freq
+* return fm_true:seek success; fm_false:seek failed
+*/
+static fm_bool mt6626_Seek(fm_u16 min_freq, fm_u16 max_freq, fm_u16 *pFreq, fm_u16 seekdir, fm_u16 space)
+{
+    fm_u16 dataRead;
+    fm_u16 freq_l;
+    fm_u16 freq_h;
+
+    mt6626_RampDown();
+    mt6626_Mute(fm_true);
+
+    WCN_DBG(FM_DBG | CHIP, "min_freq:%d, max_freq:%d\n", min_freq, max_freq);
+
+    //Program seek direction
+    mt6626_read(FM_MAIN_CFG1, &dataRead);
+    dataRead &= 0xFBFF;
+
+    if (seekdir == 0) {
+        dataRead |= 0x0000;
+    } else {
+        dataRead |= 0x0400;
+    }
+
+    WCN_DBG(FM_DBG | CHIP, "seek %s\n", seekdir ? "down" : "up");
+    //Program scan channel spacing
+    dataRead &= 0x8FFF;
+
+    if (space == 4) {
+        dataRead |= 0x4000;
+    } else {
+        dataRead |= 0x2000;
+    }
+
+    WCN_DBG(FM_DBG | CHIP, "seek space %d\n", space);
+    //enable wrap , if it is not auto scan function, 0x66[11] 0=no wrarp, 1=wrap
+    dataRead &= 0xF7FF;
+    dataRead |= 0x0800;
+    //0x66[9:0] freq upper bound
+    max_freq = (max_freq - 640) * 2;
+    dataRead &= 0xFC00;
+    dataRead |= max_freq;
+    mt6626_write(FM_MAIN_CFG1, dataRead);
+    //0x67[9:0] freq lower bound
+    mt6626_read(FM_MAIN_CFG2, &dataRead);
+    min_freq = (min_freq - 640) * 2;
+    dataRead &= 0xFC00;
+    dataRead |= min_freq;
+    mt6626_write(FM_MAIN_CFG2, dataRead);
+    //Enable STC done intr
+    mt6626_set_bits(FM_MAIN_EXTINTRMASK, FM_EXT_STC_DONE_MASK, 0xFFFE);
+    mt6626_SEEK_ON();
+
+    if (fm_wait_stc_done(MT6626_FM_STC_DONE_TIMEOUT) == fm_false) {
+        WCN_DBG(FM_ALT | CHIP, "seek, get stc done failed\n");
+        mt6626_set_bits(FM_MAIN_INTR, 0x0001, 0xFFFF);
+        mt6626_RampDown();
+        return fm_false;
+    }
+
+    //Disable STC done intr
+    mt6626_set_bits(FM_MAIN_EXTINTRMASK, 0, 0xFFFE);
+    //get the result freq
+    mt6626_read(FM_MAIN_CHANDETSTAT, &dataRead);
+    mt6626_write(FM_CHANNEL_SET, (dataRead&FM_HOST_CHAN) >> 4);
+    *pFreq = 640 + ((dataRead & FM_MAIN_CHANDET_MASK) >> (FM_MAIN_CHANDET_SHIFT + 1));
+    freq_l = fm_cust_config_fetch(FM_CFG_RX_BAND_FREQ_L);
+    freq_h = fm_cust_config_fetch(FM_CFG_RX_BAND_FREQ_H);
+    *pFreq = (*pFreq > freq_h) ? freq_h : *pFreq;
+    *pFreq = (*pFreq < freq_l) ? freq_l : *pFreq;
+    fm_cb_op->cur_freq_set(*pFreq);
+    WCN_DBG(FM_NTC | CHIP, "seek, result freq:%d\n", *pFreq);
+    mt6626_Mute(fm_false);
+
+    return fm_true;
+}
+
+static fm_bool mt6626_Scan(
+    fm_u16 min_freq, fm_u16 max_freq,
+    fm_u16 *pFreq,
+    fm_u16 *pScanTBL,
+    fm_u16 *ScanTBLsize,
+    fm_u16 scandir,
+    fm_u16 space)
+{
+    fm_u16 tmp_reg, space_val, startfreq, offset = 0;
+    fm_u16 tmp_scanTBLsize = *ScanTBLsize;
+    fm_u16 dataRead;
+
+    if ((!pScanTBL) || (tmp_scanTBLsize == 0)) {
+        WCN_DBG(FM_ALT | CHIP, "scan, failed:invalid scan table\n");
+        return fm_false;
+    }
+
+    WCN_DBG(FM_DBG | CHIP, "scan start freq: %d, max_freq:%d, min_freq:%d, scan BTL size:%d, scandir:%d, space:%d\n", *pFreq, max_freq, min_freq, *ScanTBLsize, scandir, space);
+
+    if (tmp_scanTBLsize > MT6626_SCANTBL_SIZE) {
+        tmp_scanTBLsize = MT6626_SCANTBL_SIZE;
+    }
+
+    if (space == MT6626_FM_SPACE_200K) {
+        space_val = 2; //200K
+    } else if (space == MT6626_FM_SPACE_100K) {
+        space_val = 1;  //100K
+    } else {
+        space_val = 1;  //100K
+    }
+
+    //scan up
+    if (scandir == MT6626_FM_SCAN_UP) {
+        startfreq = min_freq - space_val;
+    } else {
+        startfreq = max_freq + space_val;//max_freq compare need or not
+    }
+
+    mt6626_RampDown();
+    mt6626_Mute(fm_true);
+
+    //set freq
+    if (fm_false == mt6626_SetFreq(startfreq)) {
+        WCN_DBG(FM_ALT | CHIP, "scan, failed set freq\n");
+        return fm_false;
+    }
+
+    mt6626_RampDown();
+
+    //set space(100k/200k)and band(min_freq~max_freq) and up/down and disable wrap
+    mt6626_read(FM_MAIN_CFG2, &dataRead);
+    mt6626_write(FM_MAIN_CFG2, (dataRead&0xFC00) | ((min_freq - 640) << 1));//set space(100k/200k)and band(875~1080)and up/down
+    mt6626_read(FM_MAIN_CFG1, &dataRead);
+    mt6626_write(FM_MAIN_CFG1, (dataRead&0x8800) | (scandir << 10) | (1 << (12 + space)) | ((max_freq - 640) << 1));//set space(100k/200k)and band(875~1080)and up/down
+    mt6626_read(FM_MAIN_CFG1, &dataRead);
+    mt6626_write(FM_MAIN_CFG1, dataRead&0xF7FF); //disable wrap , if it is auto scan function
+
+    //Enable STC done intr
+    mt6626_set_bits(FM_MAIN_EXTINTRMASK, FM_EXT_STC_DONE_MASK, 0xFFFE);
+    //scan on
+    mt6626_SCAN_ON();
+
+    if (fm_wait_stc_done(MT6626_FM_STC_DONE_TIMEOUT) == fm_false) {
+        WCN_DBG(FM_ALT | CHIP, "scan, get stc done failed\n");
+        mt6626_set_bits(FM_MAIN_INTR, 0x0001, 0xFFFF);
+        mt6626_RampDown();
+
+        //get the valid freq after scan
+        mt6626_read(FM_MAIN_CHANDETSTAT, &tmp_reg);
+        tmp_reg = 640 + ((tmp_reg & FM_MAIN_CHANDET_MASK) >> (FM_MAIN_CHANDET_SHIFT + 1));
+        *pFreq = tmp_reg;
+        WCN_DBG(FM_DBG | CHIP, "scan, failed freq:%d\n", *pFreq);
+        return fm_false;
+    }
+
+    //Disable STC done intr
+    mt6626_set_bits(FM_MAIN_EXTINTRMASK, 0, 0xFFFE);
+
+    //get scan Table
+    WCN_DBG(FM_DBG | CHIP, "mt6626_Scan tbl:");
+
+    for (offset = 0; offset < tmp_scanTBLsize; offset++) {
+        mt6626_read(FM_RDS_DATA_REG, &tmp_reg);
+        *(pScanTBL + offset) = tmp_reg;
+    }
+
+    *ScanTBLsize = tmp_scanTBLsize;
+
+    //get the valid freq after scan
+    mt6626_read(FM_MAIN_CHANDETSTAT, &tmp_reg);
+    tmp_reg = 640 + ((tmp_reg & FM_MAIN_CHANDET_MASK) >> (FM_MAIN_CHANDET_SHIFT + 1));
+    *pFreq = tmp_reg;
+    WCN_DBG(FM_DBG | CHIP, "scan, after scan freq:%d\n", *pFreq);
+    mt6626_Mute(fm_false);
+
+    return fm_true;
+}
+
+/*
+ * mt6626_GetCurRSSI - get current freq's RSSI value
+ * RS=RSSI
+ * If RS>511, then RSSI(dBm)= (RS-1024)/16*6
+ *                                else RSSI(dBm)= RS/16*6
+ */
+static fm_s32 mt6626_GetCurRSSI(fm_s32 *pRSSI)
+{
+    fm_u16 tmp_reg;
+
+    mt6626_read(FM_RSSI_IND, &tmp_reg);
+    tmp_reg = tmp_reg & 0x03ff;
+
+    if (pRSSI) {
+        *pRSSI = (tmp_reg > 511) ? (((tmp_reg - 1024) * 6) >> 4) : ((tmp_reg * 6) >> 4);
+        WCN_DBG(FM_DBG | CHIP, "rssi:%d, dBm:%d\n", tmp_reg, *pRSSI);
+    } else {
+        WCN_DBG(FM_ERR | CHIP, "get rssi para error\n");
+        return -FM_EPARA;
+    }
+
+    return 0;
+}
+
+static fm_s32 mt6626_SetVol(fm_u8 vol)
+{
+#define MT6626_VOL_MAX   0x2B  // 43 volume(0-15)
+    int ret = 0;
+    fm_u8 tmp_vol = vol & 0x3f;
+    fm_u16 tmp = 0;
+
+    mt6626_read(0x60, &tmp);
+    mt6626_write(0x60, tmp&0xFFF7); //0x60 D3=0
+
+    tmp_vol = vol * 3;
+    if (tmp_vol > MT6626_VOL_MAX)
+        tmp_vol = MT6626_VOL_MAX;
+
+    ret = mt6626_set_bits(0x9C, (tmp_vol << 8), 0xC0FF);
+
+    if (ret) {
+        WCN_DBG(FM_ERR | CHIP, "Set vol=%d Failed\n", tmp_vol);
+        return ret;
+    } else {
+        WCN_DBG(FM_DBG | CHIP, "Set vol=%d OK\n", tmp_vol);
+    }
+
+    mt6626_write(0x60, tmp); //0x60 D3=1
+    return 0;
+}
+
+static fm_s32 mt6626_GetVol(fm_u8 *pVol)
+{
+    int ret = 0;
+    fm_u16 tmp_reg;
+    fm_u16 tmp = 0;
+
+    FMR_ASSERT(pVol);
+
+    mt6626_read(0x60, &tmp);
+    mt6626_write(0x60, tmp&0xFFF7); //0x60 D3=0
+
+    ret = mt6626_read(0x9C, &tmp_reg);
+
+    if (ret) {
+        *pVol = 0;
+        WCN_DBG(FM_ERR | CHIP, "Get vol Failed\n");
+        return ret;
+    } else {
+        *pVol = (tmp_reg >> 8) & 0x3f;
+        WCN_DBG(FM_DBG | CHIP, "Get vol=%d OK\n", *pVol);
+    }
+
+    mt6626_write(0x60, tmp); //0x60 D3=1
+    return 0;
+}
+
+static fm_s32 mt6626_dump_reg(void)
+{
+    return 0;
+}
+
+static fm_bool mt6626_GetMonoStereo(fm_u16 *pMonoStereo)
+{
+#define FM_BF_STEREO 0x1000
+    fm_u16 TmpReg;
+
+    if (pMonoStereo) {
+        mt6626_read(FM_RSSI_IND, &TmpReg);
+        *pMonoStereo = (TmpReg & FM_BF_STEREO) >> 12;
+    } else {
+        WCN_DBG(FM_ERR | CHIP, "MonoStero: para err\n");
+        return fm_false;
+    }
+
+    WCN_DBG(FM_DBG | CHIP, "MonoStero:0x%04x\n", *pMonoStereo);
+    return fm_true;
+}
+
+static fm_s32 mt6626_SetMonoStereo(fm_s32 MonoStereo)
+{
+    fm_s32 ret = 0;
+#define FM_FORCE_MS 0x0008
+
+    WCN_DBG(FM_DBG | CHIP, "set to %s\n", MonoStereo ? "mono" : "auto");
+
+    mt6626_write(0x60, 0x3007);
+
+    if (MonoStereo) {
+        ret = mt6626_set_bits(0x75, FM_FORCE_MS, ~FM_FORCE_MS);
+    } else {
+        ret = mt6626_set_bits(0x75, 0x0000, ~FM_FORCE_MS);
+    }
+
+    return ret;
+}
+
+static fm_s32 mt6626_GetCapArray(fm_s32 *ca)
+{
+    fm_u16 dataRead;
+    fm_u16 tmp = 0;
+
+    FMR_ASSERT(ca);
+    mt6626_read(0x60, &tmp);
+    mt6626_write(0x60, tmp&0xFFF7); //0x60 D3=0
+
+    mt6626_read(0x25, &dataRead);
+    *ca = dataRead;
+
+    mt6626_write(0x60, tmp); //0x60 D3=1
+    return 0;
+}
+
+
+/*
+ * mt6626_GetCurPamd - get current freq's PAMD value
+ * PA=PAMD
+ * If PA>511 then PAMD(dB)=  (PA-1024)/16*6,
+ *                             else PAMD(dB)=PA/16*6
+ */
+static fm_bool mt6626_GetCurPamd(fm_u16 *pPamdLevl)
+{
+    fm_u16 tmp_reg;
+    fm_u16 dBvalue;
+
+    if (mt6626_read(FM_ADDR_PAMD, &tmp_reg))
+        return fm_false;
+
+    tmp_reg &= 0x03FF;
+    dBvalue = (tmp_reg > 511) ? ((1024 - tmp_reg) * 6 / 16) : 0;
+
+    *pPamdLevl = dBvalue;
+    return fm_true;
+}
+
+static fm_s32 mt6626_ScanStop(void)
+{
+    return fm_force_active_event(FLAG_SCAN);
+}
+
+static fm_s32 mt6626_SeekStop(void)
+{
+    return fm_force_active_event(FLAG_SEEK);
+}
+
+/*
+ * mt6626_I2s_Setting - set the I2S state on MT6626
+ * @onoff - I2S on/off
+ * @mode - I2S mode: Master or Slave
+ *
+ * Return:0, if success; error code, if failed
+ */
+static fm_s32 mt6626_I2s_Setting(fm_s32 onoff, fm_s32 mode, fm_s32 sample)
+{
+    fm_u16 tmp_state = 0;
+    fm_u16 tmp_mode = 0;
+    fm_u16 tmp_sample = 0;
+    fm_s32 ret = 0;
+
+    if (onoff == MT6626_I2S_ON) {
+        tmp_state = 0x0080; //I2S Frequency tracking on, 0x61 D7=1
+    } else if (onoff == MT6626_I2S_OFF) {
+        tmp_state = 0x0000; //I2S Frequency tracking off, 0x61 D7=0
+    } else {
+        WCN_DBG(FM_ERR | CHIP, "%s():[onoff=%d]\n", __func__, onoff);
+        ret = -FM_EPARA;
+        goto out;
+    }
+
+    if (mode == MT6626_I2S_MASTER) {
+        tmp_mode = 0x03; //6620 as I2S master
+    } else if (mode == MT6626_I2S_SLAVE) {
+        tmp_mode = 0x0B; //6620 as I2S slave
+    } else {
+        WCN_DBG(FM_ERR | CHIP, "%s():[mode=%d]\n", __func__, mode);
+        ret = -FM_EPARA;
+        goto out;
+    }
+
+    if (sample == MT6626_I2S_32K) {
+        tmp_sample = 0x0000; //6620 I2S 32KHz sample rate
+    } else if (sample == MT6626_I2S_44K) {
+        tmp_sample = 0x0800; //6620 I2S 44.1KHz sample rate
+    } else if (sample == MT6626_I2S_48K) {
+        tmp_sample = 0x1000; //6620 I2S 48KHz sample rate
+    } else {
+        WCN_DBG(FM_ERR | CHIP, "%s():[sample=%d]\n", __func__, sample);
+        ret = -FM_EPARA;
+        goto out;
+    }
+
+    if ((ret = mt6626_set_bits(0x5F, tmp_sample, 0xE7FF)))
+        goto out;
+
+    if ((ret = mt6626_write(0x9B, tmp_mode)))
+        goto out;
+
+    if ((ret = mt6626_set_bits(0x61, tmp_state, 0xFF7F)))
+        goto out;
+
+    WCN_DBG(FM_NTC | CHIP, "[onoff=%s][mode=%s][sample=%d](0)33KHz,(1)44.1KHz,(2)48KHz\n",
+            (onoff == MT6626_I2S_ON) ? "On" : "Off",
+            (mode == MT6626_I2S_MASTER) ? "Master" : "Slave",
+            sample);
+out:
+    return ret;
+}
+
+static fm_bool mt6626_em_test(fm_u16 group_idx, fm_u16 item_idx, fm_u32 item_value)
+{
+    return fm_true;
+}
+
+static fm_s32 fm_low_power_wa_default(fm_s32 fmon)
+{
+    return 0;
+}
+
+fm_s32 fm_low_ops_register(struct fm_lowlevel_ops *ops)
+{
+    fm_s32 ret = 0;
+    //Basic functions.
+
+    FMR_ASSERT(ops);
+    FMR_ASSERT(ops->cb.cur_freq_get);
+    FMR_ASSERT(ops->cb.cur_freq_set);
+    fm_cb_op = &ops->cb;
+
+    //ops->bi.low_pwr_wa = mt6626_low_pwr_wa;
+    ops->bi.low_pwr_wa = fm_low_power_wa_default;
+    ops->bi.pwron = mt6626_pwron;
+    ops->bi.pwroff = mt6626_pwroff;
+    ops->bi.msdelay = Delayms;
+    ops->bi.usdelay = Delayus;
+    ops->bi.read = mt6626_read;
+    ops->bi.write = mt6626_write;
+    ops->bi.setbits = mt6626_set_bits;
+    ops->bi.chipid_get = mt6626_get_chipid;
+    ops->bi.mute = mt6626_Mute;
+    ops->bi.rampdown = mt6626_RampDown;
+    ops->bi.pwrupseq = mt6626_PowerUp;
+    ops->bi.pwrdownseq = mt6626_PowerDown;
+    ops->bi.setfreq = mt6626_SetFreq;
+    ops->bi.seek = mt6626_Seek;
+    ops->bi.seekstop = mt6626_SeekStop;
+    ops->bi.scan = mt6626_Scan;
+    ops->bi.scanstop = mt6626_ScanStop;
+    ops->bi.rssiget = mt6626_GetCurRSSI;
+    ops->bi.volset = mt6626_SetVol;
+    ops->bi.volget = mt6626_GetVol;
+    ops->bi.dumpreg = mt6626_dump_reg;
+    ops->bi.msget = mt6626_GetMonoStereo;
+    ops->bi.msset = mt6626_SetMonoStereo;
+    ops->bi.pamdget = mt6626_GetCurPamd;
+    ops->bi.em = mt6626_em_test;
+    ops->bi.anaswitch = mt6626_SetAntennaType;
+    ops->bi.anaget = mt6626_GetAntennaType;
+    ops->bi.caparray_get = mt6626_GetCapArray;
+    ops->bi.i2s_set = mt6626_I2s_Setting;
+
+    return ret;
+}
+
+fm_s32 fm_low_ops_unregister(struct fm_lowlevel_ops *ops)
+{
+    fm_s32 ret = 0;
+    //Basic functions.
+
+    FMR_ASSERT(ops);
+
+    fm_memset(&ops->bi, 0, sizeof(struct fm_basic_interface));
+    return ret;
+}
+
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6626/pub/mt6626_fm_link.c b/drivers/mtk_wcn_combo/drv_fm/mt6626/pub/mt6626_fm_link.c
new file mode 100755 (executable)
index 0000000..600245d
--- /dev/null
@@ -0,0 +1,242 @@
+/* mt6626_fm_link.c
+ *
+ * (C) Copyright 2009
+ * MediaTek <www.MediaTek.com>
+ * Hongcheng <hongcheng.xia@MediaTek.com>
+ *
+ * MT6626 FM Radio Driver -- setup data link
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/slab.h>
+#include <linux/version.h>
+#include <linux/interrupt.h>
+#include <linux/cdev.h>
+#include <asm/uaccess.h>
+#include <linux/i2c.h>
+
+#include "fm_typedef.h"
+#include "fm_dbg.h"
+#include "fm_err.h"
+#include "fm_stdlib.h"
+
+#include "mt6626_fm.h"
+#include "mt6626_fm_link.h"
+#include "mt6626_fm_reg.h"
+
+//these functions are defined after Linux2.6.32
+static int fm_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id);
+static int fm_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info);
+static int fm_i2c_remove(struct i2c_client *client);
+
+
+static const struct i2c_device_id fm_i2c_id = {MT6626_DEV, 0};
+static unsigned short force[] = {MT6626_I2C_PORT, MT6626_SLAVE_ADDR, I2C_CLIENT_END, I2C_CLIENT_END};
+static const unsigned short * const forces[] = {force, NULL};
+static struct i2c_client_address_data addr_data = {
+    .forces = forces
+};
+
+struct i2c_driver MT6626_driver = {
+    .probe = fm_i2c_probe,
+    .remove = fm_i2c_remove,
+    .detect = fm_i2c_detect,
+    .driver.name = MT6626_DEV,
+    .id_table = &fm_i2c_id,
+    .address_data = &addr_data,
+};
+
+static struct i2c_client *g_client;
+
+static int fm_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+    int ret = 0;
+
+    WCN_DBG(FM_NTC | LINK, "%s\n", __func__);
+    g_client = client;
+
+    return ret;
+}
+
+static int fm_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info)
+{
+    WCN_DBG(FM_NTC | LINK, "%s\n", __func__);
+    strcpy(info->type, MT6626_DEV);
+    return 0;
+}
+
+static int fm_i2c_remove(struct i2c_client *client)
+{
+    WCN_DBG(FM_NTC | LINK, "%s\n", __func__);
+    return 0;
+}
+
+static struct fm_link_event *link_event;
+
+fm_s32 fm_link_setup(void* data)
+{
+    if (!(link_event = kzalloc(sizeof(struct fm_link_event), GFP_KERNEL))) {
+        WCN_DBG(FM_ALT | LINK, "kzalloc(fm_link_event) -ENOMEM\n");
+        return -1;
+}
+
+    link_event->ln_event = fm_flag_event_create("ln_evt");
+
+    if (!link_event->ln_event) {
+        WCN_DBG(FM_ALT | LINK, "create mt6626_ln_event failed\n");
+        fm_free(link_event);
+        return -1;
+    }
+
+    fm_flag_event_get(link_event->ln_event);
+
+    WCN_DBG(FM_NTC | LINK, "fm link setup\n");
+    return i2c_add_driver(&MT6626_driver);
+}
+
+fm_s32 fm_link_release(void)
+{
+    fm_flag_event_put(link_event->ln_event);
+    if (link_event) {
+        fm_free(link_event);
+    }
+
+    WCN_DBG(FM_NTC | LINK, "fm link release\n");
+    i2c_del_driver(&MT6626_driver);
+    return 0;
+}
+
+/*
+ * fm_ctrl_rx
+ * the low level func to read a rigister
+ * @addr - rigister address
+ * @val - the pointer of target buf
+ * If success, return 0; else error code
+ */
+fm_s32 fm_ctrl_rx(fm_u8 addr, fm_u16 *val)
+{
+    fm_s32 n;
+    fm_u8 b[2] = {0};
+
+    // first, send addr to MT6626
+    n = i2c_master_send(g_client, (fm_u8*) & addr, 1);
+
+    if (n < 0) {
+        WCN_DBG(FM_ALT | LINK, "rx 1, [addr=0x%02X] [err=%d]\n", addr, n);
+        return -1;
+    }
+
+    // second, receive two byte from MT6626
+    n = i2c_master_recv(g_client, b, 2);
+
+    if (n < 0) {
+        WCN_DBG(FM_ALT | LINK, "rx 2, [addr=0x%02X] [err=%d]\n", addr, n);
+        return -2;
+    }
+
+    *val = ((fm_u16)b[0] << 8 | (fm_u16)b[1]);
+
+    return 0;
+}
+
+/*
+ * fm_ctrl_tx
+ * the low level func to write a rigister
+ * @addr - rigister address
+ * @val - value will be writed in the rigister
+ * If success, return 0; else error code
+ */
+fm_s32 fm_ctrl_tx(fm_u8 addr, fm_u16 val)
+{
+    fm_s32 n;
+    fm_u8 b[3];
+
+    b[0] = addr;
+    b[1] = (fm_u8)(val >> 8);
+    b[2] = (fm_u8)(val & 0xFF);
+
+    n = i2c_master_send(g_client, b, 3);
+
+    if (n < 0) {
+        WCN_DBG(FM_ALT | LINK, "tx, [addr=0x%02X] [err=%d]\n", addr, n);
+        return -1;
+    }
+
+    return 0;
+}
+
+/*
+ * fm_cmd_tx() - send cmd to FM firmware and wait event
+ * @buf - send buffer
+ * @len - the length of cmd
+ * @mask - the event flag mask
+ * @   cnt - the retry conter
+ * @timeout - timeout per cmd
+ * Return 0, if success; error code, if failed
+ */
+fm_s32 fm_cmd_tx(fm_u8* buf, fm_u16 len, fm_s32 mask, fm_s32 cnt, fm_s32 timeout, fm_s32(*callback)(struct fm_res_ctx* result))
+{
+    return 0;
+}
+
+fm_bool fm_wait_stc_done(fm_u32 sec)
+{
+    fm_s32 ret_time = 0;
+
+    ret_time = FM_EVENT_WAIT_TIMEOUT(link_event->ln_event, FLAG_TEST, sec);
+    if (!ret_time) {
+        WCN_DBG(FM_WAR | LINK, "wait stc done fail\n");
+        return fm_false;
+    } else {
+        WCN_DBG(FM_DBG | LINK, "wait stc done ok\n");
+    }
+
+    FM_EVENT_CLR(link_event->ln_event, FLAG_TEST);
+    return fm_true;
+}
+
+fm_s32 fm_event_parser(fm_s32(*rds_parser)(struct rds_rx_t*, fm_s32))
+{
+    fm_u16 tmp_reg;
+
+    fm_ctrl_rx(FM_MAIN_INTR, &tmp_reg);
+
+    if (tmp_reg&FM_INTR_STC_DONE) {
+        //clear status flag
+        fm_ctrl_tx(FM_MAIN_INTR, tmp_reg | FM_INTR_STC_DONE);
+        FM_EVENT_SEND(link_event->ln_event, FLAG_TEST);
+    }
+
+    if (tmp_reg&FM_INTR_RDS) {
+        //clear status flag
+        fm_ctrl_tx(FM_MAIN_INTR, tmp_reg | FM_INTR_RDS);
+
+        /*Handle the RDS data that we get*/
+        if (rds_parser) {
+            rds_parser(NULL, 0); //mt6626 rds lib will get rds raw data by itself
+        } else {
+            WCN_DBG(FM_WAR | LINK, "no method to parse RDS data\n");
+        }
+    }
+
+    return 0;
+}
+
+fm_s32 fm_force_active_event(fm_u32 mask)
+{
+    FM_EVENT_SEND(link_event->ln_event, FLAG_TEST);
+    return 0;
+}
+
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6626/pub/mt6626_fm_rds.c b/drivers/mtk_wcn_combo/drv_fm/mt6626/pub/mt6626_fm_rds.c
new file mode 100755 (executable)
index 0000000..3f4ccd0
--- /dev/null
@@ -0,0 +1,320 @@
+/* mt6626_rds.c
+ *
+ * (C) Copyright 2009
+ * MediaTek <www.MediaTek.com>
+ * hongcheng <hongcheng.xia@MediaTek.com>
+ *
+ * mt6626 FM Radio Driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include "fm_typedef.h"
+#include "fm_dbg.h"
+#include "fm_err.h"
+#include "fm_interface.h"
+#include "fm_stdlib.h"
+#include "fm_rds.h"
+
+#include "mt6626_fm_reg.h"
+
+
+static fm_bool bRDS_FirstIn = fm_false;
+static fm_u32 gBLER_CHK_INTERVAL = 5000;
+static fm_u16 GOOD_BLK_CNT = 0, BAD_BLK_CNT = 0;
+static fm_u8 BAD_BLK_RATIO = 0;
+
+static struct fm_callback *fm_cb = NULL;
+static struct fm_basic_interface *fm_bi = NULL;
+
+
+static fm_bool mt6626_RDS_support(void);
+static fm_s32 mt6626_RDS_enable(void);
+static fm_s32 mt6626_RDS_disable(void);
+static fm_u16 mt6626_RDS_Get_GoodBlock_Counter(void);
+static fm_u16 mt6626_RDS_Get_BadBlock_Counter(void);
+static fm_u8 mt6626_RDS_Get_BadBlock_Ratio(void);
+static fm_u32 mt6626_RDS_Get_BlerCheck_Interval(void);
+static void mt6626_RDS_GetData(fm_u16 *data, fm_u16 datalen);
+static void mt6626_RDS_Init_Data(rds_t *pstRDSData);
+
+
+
+static fm_bool mt6626_RDS_support(void)
+{
+    return fm_true;
+}
+
+static fm_s32 mt6626_RDS_enable(void)
+{
+    fm_u16 dataRead;
+
+    WCN_DBG(FM_DBG | RDSC, "rds enable\n");
+    fm_bi->read(FM_RDS_CFG0, &dataRead);
+    fm_bi->write(FM_RDS_CFG0, 6); //set buf_start_th
+    fm_bi->read(FM_MAIN_CTRL, &dataRead);
+    fm_bi->write(FM_MAIN_CTRL, dataRead | (RDS_MASK));
+
+    return 0;
+}
+
+static fm_s32 mt6626_RDS_disable(void)
+{
+    fm_u16 dataRead;
+
+    WCN_DBG(FM_DBG | RDSC, "rds disable\n");
+    fm_bi->read(FM_MAIN_CTRL, &dataRead);
+    fm_bi->write(FM_MAIN_CTRL, dataRead&(~RDS_MASK));
+
+    return 0;
+}
+
+static fm_u16 mt6626_RDS_Get_GoodBlock_Counter(void)
+{
+    fm_u16 tmp_reg;
+
+    fm_bi->read(FM_RDS_GOODBK_CNT, &tmp_reg);
+    GOOD_BLK_CNT = tmp_reg;
+    WCN_DBG(FM_DBG | RDSC, "get good block cnt:%d\n", (fm_s32)tmp_reg);
+
+    return tmp_reg;
+}
+
+static fm_u16 mt6626_RDS_Get_BadBlock_Counter(void)
+{
+    fm_u16 tmp_reg;
+
+    fm_bi->read(FM_RDS_BADBK_CNT, &tmp_reg);
+    BAD_BLK_CNT = tmp_reg;
+    WCN_DBG(FM_DBG | RDSC, "get bad block cnt:%d\n", (fm_s32)tmp_reg);
+
+    return tmp_reg;
+}
+
+static fm_u8 mt6626_RDS_Get_BadBlock_Ratio(void)
+{
+    fm_u16 tmp_reg;
+    fm_u16 gbc;
+    fm_u16 bbc;
+
+    gbc = mt6626_RDS_Get_GoodBlock_Counter();
+    bbc = mt6626_RDS_Get_BadBlock_Counter();
+
+    if ((gbc + bbc) > 0) {
+        tmp_reg = (fm_u8)(bbc * 100 / (gbc + bbc));
+    } else {
+        tmp_reg = 0;
+    }
+
+    BAD_BLK_RATIO = tmp_reg;
+    WCN_DBG(FM_DBG | RDSC, "get badblock ratio:%d\n", (fm_s32)tmp_reg);
+
+    return tmp_reg;
+}
+
+static fm_s32 mt6626_RDS_BlockCounter_Reset(void)
+{
+    mt6626_RDS_disable();
+    mt6626_RDS_enable();
+
+    return 0;
+}
+
+static fm_u32 mt6626_RDS_Get_BlerCheck_Interval(void)
+{
+    return gBLER_CHK_INTERVAL;
+}
+
+static fm_s32 mt6626_RDS_BlerCheck(rds_t *dst)
+{
+    return -1;
+}
+
+static void RDS_Recovery_Handler(void)
+{
+    fm_u16 tempData = 0;
+
+    do {
+        fm_bi->read(FM_RDS_DATA_REG, &tempData);
+        fm_bi->read(FM_RDS_POINTER, &tempData);
+    } while (tempData & 0x3);
+}
+
+static void mt6626_RDS_GetData(fm_u16 *data, fm_u16 datalen)
+{
+#define RDS_GROUP_DIFF_OFS          0x007C
+#define RDS_FIFO_DIFF               0x007F
+#define RDS_CRC_BLK_ADJ             0x0020
+#define RDS_CRC_CORR_CNT            0x001E
+#define RDS_CRC_INFO                0x0001
+
+    fm_u16 CRC = 0, i = 0, RDS_adj = 0, RDSDataCount = 0, FM_WARorrCnt = 0;
+    fm_u16 temp = 0, OutputPofm_s32 = 0;
+
+    WCN_DBG(FM_DBG | RDSC, "get data\n");
+    fm_bi->read(FM_RDS_FIFO_STATUS0, &temp);
+    RDSDataCount = ((RDS_GROUP_DIFF_OFS & temp) << 2);
+
+    if ((temp & RDS_FIFO_DIFF) >= 4) {
+        //block A data and info handling
+        fm_bi->read(FM_RDS_INFO, &temp);
+        RDS_adj |= (temp & RDS_CRC_BLK_ADJ) << 10;
+        CRC |= (temp & RDS_CRC_INFO) << 3;
+        FM_WARorrCnt |= ((temp & RDS_CRC_CORR_CNT) << 11);
+        fm_bi->read(FM_RDS_DATA_REG, &data[0]);
+
+        //block B data and info handling
+        fm_bi->read(FM_RDS_INFO, &temp);
+        RDS_adj |= (temp & RDS_CRC_BLK_ADJ) << 9;
+        CRC |= (temp & RDS_CRC_INFO) << 2;
+        FM_WARorrCnt |= ((temp & RDS_CRC_CORR_CNT) << 7);
+        fm_bi->read(FM_RDS_DATA_REG, &data[1]);
+
+        //block C data and info handling
+        fm_bi->read(FM_RDS_INFO, &temp);
+        RDS_adj |= (temp & RDS_CRC_BLK_ADJ) << 8;
+        CRC |= (temp & RDS_CRC_INFO) << 1;
+        FM_WARorrCnt |= ((temp & RDS_CRC_CORR_CNT) << 3);
+        fm_bi->read(FM_RDS_DATA_REG, &data[2]);
+
+        //block D data and info handling
+        fm_bi->read(FM_RDS_INFO, &temp);
+        RDS_adj |= (temp & RDS_CRC_BLK_ADJ) << 7;
+        CRC |= (temp & RDS_CRC_INFO);
+        FM_WARorrCnt |= ((temp & RDS_CRC_CORR_CNT) >> 1);
+        fm_bi->read(FM_RDS_DATA_REG, &data[3]);
+
+        data[4] = FM_WARorrCnt;     // CBC
+        data[5] = (CRC | RDS_adj | RDSDataCount);   //CRC
+
+        fm_bi->read(FM_RDS_PWDI, &data[6]);
+        fm_bi->read(FM_RDS_PWDQ, &data[7]);
+
+        fm_bi->read(FM_RDS_POINTER, &OutputPofm_s32);
+
+        //Go fm_s32o RDS recovery handler while RDS output pofm_s32 doesn't align to 4 in numeric
+        if (OutputPofm_s32 & 0x3) {
+            RDS_Recovery_Handler();
+        }
+
+    } else {
+        for (; i < 8; i++)
+            data[i] = 0;
+    }
+}
+
+static void mt6626_RDS_Init_Data(rds_t *pstRDSData)
+{
+    fm_memset(pstRDSData, 0, sizeof(rds_t));
+    bRDS_FirstIn = fm_true;
+
+    fm_memset(pstRDSData->RT_Data.TextData, 0x20, sizeof(pstRDSData->RT_Data.TextData));
+    fm_memset(pstRDSData->PS_Data.PS, '\0', sizeof(pstRDSData->PS_Data.PS));
+    fm_memset(pstRDSData->PS_ON, 0x20, sizeof(pstRDSData->PS_ON));
+}
+
+fm_bool mt6626_RDS_OnOff(rds_t *dst, fm_bool bFlag)
+{
+    if (mt6626_RDS_support() == fm_false) {
+        WCN_DBG(FM_ALT | RDSC, "mt6626_RDS_OnOff failed, RDS not support\n");
+        return fm_false;
+    }
+
+    if (bFlag) {
+        mt6626_RDS_Init_Data(dst);
+        mt6626_RDS_enable();
+    } else {
+        mt6626_RDS_disable();
+    }
+
+    return fm_true;
+}
+
+DEFINE_RDSLOG(rds_log);
+
+/* mt6626_RDS_Efm_s32_Handler    -    response FM RDS interrupt
+ * @fm - main data structure of FM driver
+ * This function first get RDS raw data, then call RDS spec parser
+ */
+static fm_s32 mt6626_rds_parser(rds_t *rds_dst, struct rds_rx_t *rds_raw, fm_s32 rds_size, fm_u16(*getfreq)(void))
+{
+    struct rds_rx_t raw;
+    fm_u16 fifo_offset;
+
+    do {
+        mt6626_RDS_GetData(&raw.data[0].blkA, sizeof(rds_packet_t) + 2);
+        fifo_offset = (raw.data[0].crc & FM_RDS_DCO_FIFO_OFST) >> 5; //FM_RDS_DATA_CRC_FFOST
+        WCN_DBG(FM_DBG | RDSC, "RDS fifo_offset:%d\n", fifo_offset);
+        rds_log.log_in(&rds_log, &raw, sizeof(rds_packet_t) + 2*sizeof(fm_u16));
+        rds_parser(rds_dst, &raw, sizeof(rds_packet_t) + 2*sizeof(fm_u16), getfreq);
+    } while (fifo_offset > 1);
+
+    return 0;
+}
+
+static fm_s32 mt6626_rds_log_get(struct rds_rx_t *dst, fm_s32 *dst_len)
+{
+    return rds_log.log_out(&rds_log, dst, dst_len);
+}
+
+static fm_s32 mt6626_rds_gc_get(struct rds_group_cnt_t *dst, rds_t *rdsp)
+{
+    return rds_grp_counter_get(dst, &rdsp->gc);
+}
+
+static fm_s32 mt6626_rds_gc_reset(rds_t *rdsp)
+{
+    return rds_grp_counter_reset(&rdsp->gc);
+}
+
+fm_s32 fm_rds_ops_register(struct fm_lowlevel_ops *ops)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(ops);
+    FMR_ASSERT(ops->bi.write);
+    FMR_ASSERT(ops->bi.read);
+    FMR_ASSERT(ops->bi.setbits);
+    FMR_ASSERT(ops->bi.usdelay);
+    fm_bi = &ops->bi;
+
+    FMR_ASSERT(ops->cb.cur_freq_get);
+    FMR_ASSERT(ops->cb.cur_freq_set);
+    fm_cb = &ops->cb;
+
+    ops->ri.rds_blercheck = mt6626_RDS_BlerCheck;
+    ops->ri.rds_onoff = mt6626_RDS_OnOff;
+    ops->ri.rds_parser = mt6626_rds_parser;
+    ops->ri.rds_gbc_get = mt6626_RDS_Get_GoodBlock_Counter;
+    ops->ri.rds_bbc_get = mt6626_RDS_Get_BadBlock_Counter;
+    ops->ri.rds_bbr_get = mt6626_RDS_Get_BadBlock_Ratio;
+    ops->ri.rds_bc_reset = mt6626_RDS_BlockCounter_Reset;
+    ops->ri.rds_bci_get = mt6626_RDS_Get_BlerCheck_Interval;
+    ops->ri.rds_log_get = mt6626_rds_log_get;
+    ops->ri.rds_gc_get = mt6626_rds_gc_get;
+    ops->ri.rds_gc_reset = mt6626_rds_gc_reset;
+    return ret;
+}
+
+fm_s32 fm_rds_ops_unregister(struct fm_lowlevel_ops *ops)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(ops);
+
+    fm_bi = NULL;
+    fm_memset(&ops->ri, 0, sizeof(struct fm_rds_interface));
+    return ret;
+}
+
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6628/inc/mt6628_drv_dsp.h b/drivers/mtk_wcn_combo/drv_fm/mt6628/inc/mt6628_drv_dsp.h
new file mode 100755 (executable)
index 0000000..f333f7e
--- /dev/null
@@ -0,0 +1,10639 @@
+
+const unsigned char channel_parameter[] = {
+0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,1
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,2
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,1
+,1
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,1
+,1
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,2
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,1
+,1
+,1
+,1
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,1
+,0
+,0
+,0
+,0
+,0
+,2
+,0
+,0
+,0
+,0
+,5
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,1
+,1
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,2
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,0
+,1
+,1
+,1
+,0
+,0
+,0
+};
+
+#if defined(MT6626_FPGA)
+const unsigned short bin_rom[] = {
+0x0000
+,0x1FFF
+,0xBC00
+,0x0010
+,0xBC00
+,0x0271
+,0x8EC8
+,0x8E00
+,0x8EC8
+,0x8E00
+,0x8EC8
+,0x8E00
+,0x8EC8
+,0x8E00
+,0x8EC8
+,0x8E00
+,0x8EC8
+,0x8E00
+,0xBC02
+,0x0906
+,0xBC20
+,0x2019
+,0x4021
+,0xFB11
+,0xBC02
+,0x0807
+,0xBC20
+,0x2019
+,0x4041
+,0xFB11
+,0xBC22
+,0x0480
+,0xBC20
+,0x0080
+,0x4001
+,0x8B02
+,0xE401
+,0xBC21
+,0x0367
+,0xA301
+,0x0080
+,0xBC20
+,0x201A
+,0x41E1
+,0xFA12
+,0xA302
+,0x0082
+,0x0891
+,0x2620
+,0x8FF9
+,0x3D02
+,0xBC21
+,0x2018
+,0x481E
+,0xBC22
+,0x2019
+,0x8C69
+,0x40C0
+,0xA203
+,0x0082
+,0x2631
+,0x8F4B
+,0x2634
+,0x8F3E
+,0x2632
+,0x8F1D
+,0xB306
+,0x0008
+,0x8F0A
+,0x40E0
+,0xFB50
+,0xBC02
+,0x1E58
+,0xBC22
+,0x2019
+,0xBC21
+,0x2018
+,0x481E
+,0x8C53
+,0x40C0
+,0xFB50
+,0xFA33
+,0x26B0
+,0x8F08
+,0xBC02
+,0x072A
+,0xBC21
+,0x2018
+,0x4020
+,0x7207
+,0xBB30
+,0x40C0
+,0xBC22
+,0x2019
+,0xA31E
+,0x0082
+,0x8D41
+,0x40A0
+,0x70E0
+,0x3B50
+,0xBC21
+,0x201D
+,0xBC22
+,0x201B
+,0xFA31
+,0xFA52
+,0x0810
+,0xBC3E
+,0x00E4
+,0xBC3A
+,0x0692
+,0xB400
+,0x0002
+,0xA31E
+,0x0083
+,0xA31A
+,0x0084
+,0x0408
+,0xBC02
+,0x0131
+,0x40C0
+,0xBC22
+,0x2019
+,0xBC21
+,0x2018
+,0x481E
+,0x8D23
+,0x4080
+,0xFB50
+,0xBC02
+,0x016B
+,0x40C0
+,0xBC22
+,0x2019
+,0xBC21
+,0x2018
+,0x481E
+,0x8D18
+,0x4060
+,0xBC21
+,0x201F
+,0xFB50
+,0xFA30
+,0xBC3E
+,0x00C8
+,0xBC3A
+,0x0652
+,0xBC21
+,0x03FF
+,0xA31E
+,0x0083
+,0xA31A
+,0x0084
+,0x0801
+,0xBC02
+,0x0131
+,0x40C0
+,0xBC22
+,0x2019
+,0xBC21
+,0x2018
+,0x481E
+,0xA203
+,0x0082
+,0xB316
+,0x0040
+,0x8F91
+,0xBC00
+,0x001C
+,0x6915
+,0xA902
+,0x8E00
+,0xA30E
+,0x0085
+,0xDFD5
+,0xBC02
+,0x0607
+,0xBC02
+,0x077A
+,0xBC20
+,0x2019
+,0x7040
+,0x4FD5
+,0xBC22
+,0x2008
+,0xFB11
+,0xFA51
+,0xBC23
+,0x4000
+,0x0ACB
+,0xBC21
+,0x2100
+,0xFB53
+,0xFA32
+,0xB314
+,0x0020
+,0x8FFB
+,0x4121
+,0xE9FE
+,0xFB11
+,0xBC00
+,0x1D52
+,0xE902
+,0xBC20
+,0x2019
+,0x7060
+,0x5FD5
+,0x8C02
+,0xFB11
+,0x8E00
+,0xA200
+,0x008B
+,0x2600
+,0x8FFA
+,0x3E02
+,0xA200
+,0x008C
+,0x6980
+,0x4FD5
+,0x8F02
+,0xA200
+,0x0086
+,0x2681
+,0x8F02
+,0x4080
+,0xA300
+,0x0082
+,0x8EC0
+,0xE9FE
+,0x8E00
+,0xE902
+,0xBC20
+,0x2019
+,0x7068
+,0x5FD5
+,0x8C02
+,0xFB11
+,0x8E00
+,0xA200
+,0x008B
+,0x2600
+,0x8FFA
+,0x3E02
+,0xA200
+,0x008C
+,0xA201
+,0x0088
+,0x2681
+,0x8F06
+,0x4020
+,0xA202
+,0x008A
+,0x1401
+,0x0A10
+,0xA300
+,0x008A
+,0x3409
+,0xA300
+,0x0088
+,0xA201
+,0x0086
+,0xB300
+,0x0010
+,0x8F01
+,0x2691
+,0x8F09
+,0x401C
+,0xBC20
+,0x2041
+,0xA202
+,0x008A
+,0xA31C
+,0x0088
+,0xA31C
+,0x008A
+,0xFB12
+,0x2691
+,0x8F16
+,0xBC20
+,0x2019
+,0x41C1
+,0x7008
+,0x7B11
+,0xBC22
+,0x2018
+,0xBC20
+,0x201A
+,0x8C05
+,0xFB51
+,0x8E00
+,0xBC20
+,0x201A
+,0x8E00
+,0xFA10
+,0xB310
+,0x0008
+,0x8FF6
+,0x7040
+,0x0FD5
+,0x8C03
+,0xA300
+,0x0082
+,0xCFD5
+,0x8E00
+,0x8EC0
+,0xE9FE
+,0x8E00
+,0xE902
+,0x8E00
+,0xDFC0
+,0xDFF5
+,0xBC02
+,0x05A2
+,0xA200
+,0x0087
+,0x2680
+,0x8F0C
+,0xBC20
+,0x2040
+,0x7000
+,0x4FC3
+,0x700F
+,0xBB11
+,0x4042
+,0xA303
+,0x0089
+,0xA31E
+,0x0087
+,0xA301
+,0x0086
+,0xFB12
+,0xA200
+,0x0084
+,0x8EA0
+,0xBC20
+,0x02C7
+,0xA300
+,0x009B
+,0xBC02
+,0x00A7
+,0x3E01
+,0xBC20
+,0x2008
+,0xBC21
+,0x033D
+,0xA202
+,0x0083
+,0xFB11
+,0x8EA2
+,0xBC20
+,0x2008
+,0x7000
+,0x4FF5
+,0xBC22
+,0x201A
+,0x7040
+,0x3B11
+,0xFA51
+,0x2248
+,0x8F00
+,0xA300
+,0x0082
+,0x8EC0
+,0xE9FE
+,0x8E00
+,0xE902
+,0x8E00
+,0xDFD5
+,0xBC02
+,0x0480
+,0xBC20
+,0x02B3
+,0xA300
+,0x009B
+,0xBC02
+,0x00A7
+,0x3E01
+,0xBC20
+,0x2008
+,0xBC21
+,0x03F7
+,0xBC22
+,0x2018
+,0x7008
+,0x3B11
+,0x7050
+,0x3B50
+,0xBC21
+,0x2019
+,0x8C2E
+,0xFB30
+,0xA200
+,0x0081
+,0x2601
+,0x8F04
+,0xBC21
+,0x8000
+,0xBC20
+,0x2023
+,0x8C24
+,0xFB11
+,0xBC02
+,0x01BE
+,0xA200
+,0x0085
+,0x4001
+,0xA301
+,0x0081
+,0x2682
+,0x8F02
+,0x4100
+,0xA300
+,0x0082
+,0xBC02
+,0x1E58
+,0xBC20
+,0x201A
+,0x8E00
+,0xFA10
+,0xB310
+,0x0008
+,0x8F05
+,0xBC20
+,0x2019
+,0x4161
+,0x7008
+,0x3B11
+,0xA300
+,0x0085
+,0xBC02
+,0x077A
+,0xBC20
+,0x2023
+,0xBC21
+,0x8000
+,0xFB11
+,0xA200
+,0x0082
+,0x2604
+,0x8FCE
+,0x3E02
+,0x7000
+,0x4FD5
+,0xBC20
+,0x2008
+,0x8EC0
+,0xE9FE
+,0xFB11
+,0xE902
+,0xA200
+,0x0098
+,0x6CE0
+,0x1FD5
+,0x8F57
+,0xBC02
+,0x0918
+,0xBC20
+,0x01AE
+,0xBC02
+,0x09F0
+,0xA200
+,0x02A7
+,0x2682
+,0x8F02
+,0xBC20
+,0x01AE
+,0xBC02
+,0x0D50
+,0xA200
+,0x008E
+,0x2606
+,0x8F1E
+,0x2604
+,0x8F17
+,0x2602
+,0x8F0B
+,0x2600
+,0x8F05
+,0xA200
+,0x008D
+,0x2680
+,0x8F20
+,0xBC02
+,0x0BDE
+,0x8D1F
+,0xBC02
+,0x0E6E
+,0x8D1C
+,0xBC20
+,0x2032
+,0x4101
+,0xFA10
+,0x0801
+,0xA300
+,0x01E3
+,0xBC02
+,0x0A17
+,0x8D12
+,0xBC02
+,0x0AA2
+,0xBC02
+,0x0CA4
+,0x8D0D
+,0xA200
+,0x0085
+,0x2601
+,0x8F05
+,0xA200
+,0x02C7
+,0x2601
+,0x8F01
+,0xBC02
+,0x0B48
+,0x8D02
+,0xBC02
+,0x0B2B
+,0xA201
+,0x01BE
+,0xBC20
+,0x01AE
+,0xBC02
+,0x0A72
+,0xBC20
+,0x01E7
+,0xBC02
+,0x0B04
+,0xA200
+,0x0266
+,0x2680
+,0xBC20
+,0x01E7
+,0x8F03
+,0xBC21
+,0x7FFF
+,0xBC02
+,0x0B8C
+,0x8D04
+,0xA201
+,0x01FF
+,0xBC02
+,0x0B8C
+,0xBC02
+,0x0C54
+,0xA200
+,0x0099
+,0x2600
+,0x8F02
+,0xBC02
+,0x195E
+,0xBC02
+,0x1926
+,0xA200
+,0x009A
+,0x2600
+,0x8F02
+,0xB000
+,0xFFFF
+,0xA300
+,0x009A
+,0xBC20
+,0x2040
+,0x4021
+,0xFA10
+,0x0801
+,0x2600
+,0x8F0A
+,0xBC20
+,0x2023
+,0xBC21
+,0x4000
+,0xFA10
+,0x0801
+,0x2680
+,0x8F02
+,0xA200
+,0x009A
+,0x2600
+,0x8F15
+,0x3E02
+,0x4000
+,0xA300
+,0x0099
+,0x3E01
+,0xBC20
+,0x2008
+,0xBC21
+,0x0080
+,0xFA12
+,0x0851
+,0x2610
+,0x8F0B
+,0xFA11
+,0xBC22
+,0xFF7F
+,0x084A
+,0x7000
+,0x3B11
+,0xBC02
+,0x05B3
+,0x8D03
+,0x4020
+,0xA300
+,0x0099
+,0x7038
+,0x4FD5
+,0xA200
+,0x008E
+,0xE9FE
+,0x3401
+,0x8EC0
+,0x0801
+,0xA300
+,0x008E
+,0x4020
+,0xBC21
+,0x00C0
+,0xA300
+,0x0091
+,0xA300
+,0x0092
+,0xA301
+,0x0098
+,0x8EC0
+,0xA300
+,0x0090
+,0xA300
+,0x008F
+,0xE918
+,0x8E00
+,0xDD05
+,0xBC25
+,0x2096
+,0xDD5B
+,0xFAB5
+,0xA205
+,0x009B
+,0xDD7A
+,0xDD9F
+,0xDDBE
+,0xDDDD
+,0xDDFC
+,0xDE0B
+,0xDE2C
+,0xDE49
+,0xDE68
+,0xDE8F
+,0xDEAE
+,0xDED5
+,0xDEE6
+,0xDF04
+,0xDF23
+,0xDF42
+,0xDF61
+,0xDF80
+,0xDD27
+,0xF9FC
+,0x8EA5
+,0xBC20
+,0x2096
+,0xBC21
+,0x00FF
+,0xFA10
+,0x6220
+,0x4D05
+,0xA203
+,0x0096
+,0x6854
+,0xCD27
+,0x6624
+,0xCF80
+,0xA302
+,0x0096
+,0xCF61
+,0xCF42
+,0xCF23
+,0xCF04
+,0xCEE6
+,0xCDFC
+,0xCDDD
+,0xCDBE
+,0xCD9F
+,0xCD7A
+,0xCD5B
+,0xF8FC
+,0xCED5
+,0xCEAE
+,0xCE8F
+,0xCE68
+,0xCE49
+,0xCE2C
+,0xCE0B
+,0xE9E8
+,0x8EC8
+,0xBC20
+,0x2102
+,0xBC21
+,0x8000
+,0xFA10
+,0x0801
+,0x6980
+,0x2902
+,0x8F07
+,0xDFD5
+,0xBC02
+,0x02DB
+,0xBC20
+,0x02DB
+,0xCFD5
+,0xA300
+,0x009B
+,0x8EC0
+,0xE9FE
+,0x8E00
+,0xBC20
+,0x2104
+,0xBC21
+,0x8000
+,0xFA10
+,0x0801
+,0x6980
+,0x2902
+,0x8F07
+,0xDFD5
+,0xBC02
+,0x0423
+,0xBC20
+,0x0423
+,0xCFD5
+,0xA300
+,0x009B
+,0x8EC0
+,0xE9FE
+,0x8E00
+,0xE906
+,0xA202
+,0x0090
+,0x69A8
+,0x1F95
+,0x8F19
+,0xBC24
+,0x2081
+,0xBC23
+,0x2082
+,0xFA95
+,0xBC24
+,0x2015
+,0xFA73
+,0xA21A
+,0x0461
+,0xA21E
+,0x046B
+,0xA210
+,0x0361
+,0xFA94
+,0xA305
+,0x02CA
+,0xA303
+,0x02CB
+,0xA310
+,0x02C8
+,0xA31A
+,0x02C9
+,0xA304
+,0x02CC
+,0xA31E
+,0x02CD
+,0x26A6
+,0x8F32
+,0xBC23
+,0x027F
+,0xBC24
+,0x026F
+,0x4022
+,0xBD10
+,0x0306
+,0xE205
+,0xE585
+,0xA21C
+,0x02C8
+,0xA21A
+,0x02CA
+,0xA21E
+,0x02CB
+,0xA210
+,0x02C9
+,0xA205
+,0x02CC
+,0xA203
+,0x02CD
+,0xA204
+,0x0081
+,0xA31C
+,0x02C2
+,0xA310
+,0x02C3
+,0xA31A
+,0x02C4
+,0xA31E
+,0x02C5
+,0xA305
+,0x02C6
+,0xA303
+,0x02C7
+,0x2640
+,0x8F03
+,0xA203
+,0x0095
+,0x34D9
+,0xA303
+,0x0095
+,0xA203
+,0x0098
+,0xA302
+,0x0081
+,0x3230
+,0x8F02
+,0xB026
+,0xFFFF
+,0xA302
+,0x0098
+,0xA200
+,0x028F
+,0x421E
+,0x403A
+,0xBC3C
+,0x027F
+,0xBC22
+,0x2033
+,0xE064
+,0xBC23
+,0x2034
+,0xE065
+,0xFB54
+,0xFB75
+,0xA300
+,0x028F
+,0xBC02
+,0x1BC3
+,0xBC22
+,0x3105
+,0xA200
+,0x0313
+,0x700E
+,0xBA52
+,0x3BC2
+,0xBC22
+,0x2139
+,0xBC3C
+,0x02E0
+,0xBD05
+,0x0352
+,0xFA53
+,0xE463
+,0xA202
+,0x0099
+,0x2620
+,0xA300
+,0x0313
+,0x385A
+,0x8F10
+,0xBC23
+,0x2008
+,0xBC24
+,0x0080
+,0xFA75
+,0x0B2C
+,0xBC25
+,0x2103
+,0xFB74
+,0xFAB3
+,0xBC24
+,0x4000
+,0x08DC
+,0x2630
+,0x8F01
+,0xBC02
+,0x15BE
+,0x4022
+,0xA203
+,0x0091
+,0x26B0
+,0x8F05
+,0xBC20
+,0x2012
+,0xBC21
+,0x2014
+,0xBC02
+,0x106C
+,0x4022
+,0xA203
+,0x0093
+,0xB306
+,0x0011
+,0x4003
+,0x1893
+,0xA204
+,0x0091
+,0x6D28
+,0x5FA2
+,0x4244
+,0x2214
+,0x18DA
+,0xA202
+,0x008F
+,0x2620
+,0xA303
+,0x0091
+,0x8F67
+,0x2621
+,0x8F53
+,0x2622
+,0x8F2B
+,0x26A3
+,0x8F26
+,0xBC02
+,0x118C
+,0xCFA2
+,0x2620
+,0xBC20
+,0x2015
+,0x8F0E
+,0xA201
+,0x0097
+,0xBC02
+,0x101D
+,0xBC02
+,0x1391
+,0xBC02
+,0x1DAA
+,0xA202
+,0x0097
+,0x2622
+,0x4043
+,0x8F00
+,0x34D1
+,0xA303
+,0x0097
+,0xA202
+,0x0093
+,0x3511
+,0x4242
+,0x21E2
+,0xA203
+,0x0094
+,0x4005
+,0x34D9
+,0x192C
+,0x4062
+,0x08DA
+,0xA304
+,0x0093
+,0x8C51
+,0xA303
+,0x0094
+,0x8C4E
+,0x4062
+,0x3854
+,0xB004
+,0xFFFB
+,0xDFC0
+,0xBC02
+,0x121B
+,0x6E15
+,0x0FC0
+,0xB014
+,0xFFFA
+,0xDFC1
+,0xBC02
+,0x1277
+,0xBC02
+,0x12BC
+,0xCFC0
+,0xBC21
+,0x0464
+,0xBC02
+,0x1326
+,0x7018
+,0x8FA3
+,0x2630
+,0x8F33
+,0xA201
+,0x0097
+,0xBC20
+,0x2013
+,0xBC02
+,0x1037
+,0xA201
+,0x0097
+,0xBC20
+,0x200B
+,0xBC02
+,0x1092
+,0x4062
+,0x8D27
+,0xBC02
+,0x118C
+,0xBC02
+,0x11E4
+,0xBC02
+,0x1B03
+,0x7018
+,0x8FA3
+,0x2630
+,0x8F1B
+,0xA201
+,0x0097
+,0xBC20
+,0x2011
+,0xBC02
+,0x10B6
+,0x4062
+,0x8D15
+,0xBC02
+,0x12BC
+,0xCFA2
+,0x2620
+,0x8F00
+,0xBC02
+,0x1E00
+,0xBC02
+,0x10FF
+,0xA202
+,0x0094
+,0x26A0
+,0x4062
+,0x8F05
+,0xA203
+,0x047B
+,0x2630
+,0x8F01
+,0xBC02
+,0x115E
+,0x4062
+,0xA204
+,0x008F
+,0xA203
+,0x0090
+,0x6D48
+,0x4F95
+,0x34D9
+,0x40E6
+,0xA205
+,0x008D
+,0x08DE
+,0x08A2
+,0x26D0
+,0xA303
+,0x0090
+,0xA302
+,0x008F
+,0x8F04
+,0xBC22
+,0x31F8
+,0xDF95
+,0xFA52
+,0x8EA2
+,0xCF95
+,0x8E00
+,0x8EC0
+,0xE9FA
+,0x8E00
+,0xE902
+,0xA200
+,0x0092
+,0xDFC0
+,0xDFF5
+,0xBC02
+,0x10DC
+,0xCFC0
+,0xB300
+,0x0044
+,0x8F2B
+,0xA201
+,0x0097
+,0xB300
+,0x0045
+,0x8F21
+,0xB300
+,0x0046
+,0x8F14
+,0xCFC0
+,0xB310
+,0x0047
+,0x8F21
+,0xA200
+,0x0470
+,0x2680
+,0x8F00
+,0xBC02
+,0x0F91
+,0xBC02
+,0x1DAA
+,0xA200
+,0x0097
+,0x2602
+,0x4041
+,0x8F00
+,0x3441
+,0xA301
+,0x0097
+,0x8D12
+,0xBC20
+,0x2013
+,0xBC02
+,0x1037
+,0xA201
+,0x0097
+,0xBC20
+,0x200B
+,0xBC02
+,0x1092
+,0x8D07
+,0xBC20
+,0x2011
+,0xBC02
+,0x10B6
+,0x8D02
+,0xBC02
+,0x1E00
+,0x7240
+,0x4FC0
+,0x6D00
+,0x4FF5
+,0x21C1
+,0x4001
+,0x1808
+,0xA201
+,0x008D
+,0x2690
+,0xA300
+,0x0092
+,0x8F04
+,0xBC20
+,0x31F8
+,0xDFD5
+,0xFA10
+,0x8EA0
+,0xCFD5
+,0x8E00
+,0x8EC0
+,0xE9FE
+,0x8E00
+,0xBC20
+,0x009C
+,0xBC21
+,0x047C
+,0x0448
+,0x3489
+,0x32A0
+,0x4001
+,0x8F01
+,0x8B02
+,0xE401
+,0x8EB8
+,0xE902
+,0x8E00
+,0xDFD5
+,0xBC02
+,0x0474
+,0xBC20
+,0x3173
+,0xBC21
+,0x3010
+,0xBC24
+,0x02A8
+,0xBC22
+,0x2032
+,0x7014
+,0x3A10
+,0x4085
+,0x700F
+,0x3A31
+,0xA300
+,0x01E5
+,0xFA53
+,0xBC40
+,0x1605
+,0xA301
+,0x0467
+,0x4100
+,0xBC40
+,0x1E10
+,0xBC40
+,0x2610
+,0x6206
+,0x2610
+,0xFA51
+,0x6213
+,0x6650
+,0xBC3A
+,0x0184
+,0xBC3E
+,0x01C0
+,0x4503
+,0x4444
+,0xBC2E
+,0x0160
+,0xBC2F
+,0x0170
+,0xB048
+,0x009C
+,0xB056
+,0x009C
+,0xA300
+,0x01E3
+,0xA301
+,0x01F7
+,0xA31C
+,0x0468
+,0xA31C
+,0x0461
+,0xA31C
+,0x045C
+,0xA30E
+,0x016E
+,0xA30F
+,0x017E
+,0xA31A
+,0x01AC
+,0xA31A
+,0x01AD
+,0xA31E
+,0x01E0
+,0xA31E
+,0x01E1
+,0xA304
+,0x015E
+,0xA305
+,0x015F
+,0xBC20
+,0x3136
+,0xBC21
+,0x3163
+,0xBD04
+,0x04D2
+,0xFA04
+,0xFB24
+,0xFA0C
+,0xFB24
+,0xBD04
+,0x04D8
+,0xFA0C
+,0xFB24
+,0xBC20
+,0x31B2
+,0x7717
+,0xBA51
+,0x7006
+,0xBA14
+,0x38BC
+,0x084D
+,0xB048
+,0x319C
+,0xA301
+,0x0266
+,0xBC20
+,0x0200
+,0xFA91
+,0xB040
+,0x0050
+,0xB060
+,0x0010
+,0xA304
+,0x0261
+,0xA300
+,0x0260
+,0xA306
+,0x0262
+,0xFA52
+,0x4044
+,0x1609
+,0x41E6
+,0x0894
+,0x1406
+,0xB4F2
+,0x0001
+,0x0B07
+,0xBC20
+,0x01F9
+,0xA302
+,0x02A7
+,0xBC40
+,0x1C01
+,0xBC40
+,0x3401
+,0x144E
+,0x24A1
+,0xBC24
+,0x029A
+,0xBC40
+,0x140C
+,0xBC21
+,0x0267
+,0xBC22
+,0x0294
+,0xBC3C
+,0x4000
+,0x6D79
+,0x640E
+,0xBC3F
+,0x0285
+,0xBC3B
+,0x0290
+,0xBC30
+,0x2000
+,0x7000
+,0x244F
+,0xBC40
+,0x6607
+,0xA31F
+,0x028F
+,0xA31B
+,0x0293
+,0xBC40
+,0x0C9C
+,0xBC40
+,0x149C
+,0xBC40
+,0x151E
+,0xBC40
+,0x2C80
+,0xBC40
+,0x3490
+,0xBC40
+,0x3C9A
+,0xBC40
+,0x2D10
+,0xBC40
+,0x1D03
+,0x40A7
+,0xBC02
+,0x05B3
+,0xB04A
+,0x0318
+,0xBC23
+,0x30FD
+,0xBC22
+,0x30FF
+,0xA304
+,0x0325
+,0xFA74
+,0xFA52
+,0x04F2
+,0xBC21
+,0x02E0
+,0x3589
+,0xB00E
+,0x0318
+,0xA306
+,0x0312
+,0xA300
+,0x0326
+,0xBC26
+,0x30FC
+,0xBC20
+,0x3102
+,0xFAD6
+,0xFA10
+,0xA306
+,0x0360
+,0x14AA
+,0x1428
+,0x14EB
+,0xA304
+,0x035F
+,0xBC26
+,0x2021
+,0x35CD
+,0xBC25
+,0x0327
+,0xBC24
+,0x07C0
+,0xBC3E
+,0x7FFF
+,0xBC3A
+,0x0320
+,0xB012
+,0x0019
+,0xB024
+,0xFFFF
+,0xB000
+,0xFFFF
+,0x6D4B
+,0x3BD4
+,0xA305
+,0x0354
+,0xA31E
+,0x047A
+,0xA31A
+,0x02DC
+,0xA301
+,0x0314
+,0xA307
+,0x0313
+,0xA304
+,0x0353
+,0xA302
+,0x0363
+,0xA303
+,0x0364
+,0xA300
+,0x0365
+,0xBC02
+,0x0263
+,0xBC02
+,0x07A4
+,0xBC20
+,0x2023
+,0xBC21
+,0x4000
+,0x700F
+,0xBA10
+,0x0801
+,0x2680
+,0x8F09
+,0xBC20
+,0x2040
+,0x7008
+,0x4FD5
+,0xFA10
+,0x0801
+,0x2600
+,0x8F10
+,0xA301
+,0x0099
+,0x8D0F
+,0xBC20
+,0x2008
+,0xBC21
+,0xFF7F
+,0x7007
+,0x3A12
+,0x6214
+,0x4FD5
+,0xA31C
+,0x0099
+,0xA31C
+,0x02A7
+,0xA31E
+,0x008D
+,0xFB11
+,0x8EC0
+,0xE9FE
+,0x8E00
+,0xE902
+,0x8E00
+,0xDFD5
+,0xBC02
+,0x0474
+,0x6914
+,0x4FD5
+,0x4020
+,0xE9FE
+,0xA309
+,0x008B
+,0xA309
+,0x008C
+,0xA300
+,0x00A0
+,0xBC00
+,0x0263
+,0xBC22
+,0x036A
+,0xBC21
+,0x044C
+,0x044A
+,0x3509
+,0x32C0
+,0x4001
+,0x4023
+,0x8F01
+,0x8B04
+,0xE501
+,0x2680
+,0x8F02
+,0xBC22
+,0x2040
+,0x8E00
+,0xFB51
+,0xBC22
+,0x305A
+,0x40BC
+,0x703F
+,0xBA52
+,0xBC3A
+,0x0376
+,0xBC2E
+,0x0399
+,0x4FEF
+,0xBC28
+,0x03A8
+,0x2680
+,0x149A
+,0x4270
+,0xA31E
+,0x0372
+,0xA31A
+,0x0375
+,0xA310
+,0x0395
+,0xA31C
+,0x0396
+,0xA31C
+,0x0397
+,0xA30E
+,0x0398
+,0xA30F
+,0x03B8
+,0xA308
+,0x03A6
+,0xA302
+,0x03A5
+,0xBC20
+,0x2040
+,0x8F01
+,0x4042
+,0xFB12
+,0xBC20
+,0x3079
+,0xBC3E
+,0x03DC
+,0xBC3A
+,0x041A
+,0xBC24
+,0x2044
+,0xFA03
+,0xBC30
+,0x03F1
+,0xA31E
+,0x03DB
+,0xA31A
+,0x0442
+,0xA310
+,0x03F0
+,0xFB91
+,0xA301
+,0x03E2
+,0xA303
+,0x03E0
+,0xBC22
+,0x2043
+,0x8EC0
+,0xA300
+,0x03E1
+,0xFB51
+,0xE902
+,0xA200
+,0x008C
+,0xA201
+,0x0082
+,0x6980
+,0x5FD5
+,0x8F16
+,0x2611
+,0x8F14
+,0x2612
+,0x8F11
+,0xBC20
+,0x201A
+,0x4201
+,0xFA10
+,0x0801
+,0x2680
+,0x8F00
+,0xBC02
+,0x06A8
+,0xBC20
+,0x201F
+,0xBC21
+,0x03FF
+,0xFA10
+,0x0801
+,0xBC22
+,0x2002
+,0x8C06
+,0xFB50
+,0xBC20
+,0x2002
+,0xA201
+,0x0089
+,0xFB11
+,0xBC20
+,0x2000
+,0x4021
+,0xFB11
+,0xFA11
+,0x2693
+,0x8FFC
+,0x8E00
+,0xBC20
+,0x2000
+,0x4001
+,0xBC22
+,0x2020
+,0x7010
+,0x3B11
+,0xFA51
+,0x0808
+,0x2600
+,0x4021
+,0x8F0C
+,0xBC20
+,0x2001
+,0x8E00
+,0xFB11
+,0xFA11
+,0x2693
+,0x8FFC
+,0x8E00
+,0x7000
+,0x4FD5
+,0xBC20
+,0x2001
+,0x8C02
+,0xFB11
+,0xCFD5
+,0x8E00
+,0x8EC0
+,0xE9FE
+,0x8E00
+,0xBC20
+,0x201B
+,0x4022
+,0xFA10
+,0x4381
+,0x0902
+,0x0841
+,0x4043
+,0x2640
+,0x0803
+,0x124B
+,0xA204
+,0x0089
+,0xBC23
+,0x201D
+,0x8F10
+,0x0461
+,0xFA73
+,0xA301
+,0x0089
+,0x218B
+,0x8F1A
+,0x2600
+,0xBC20
+,0x201C
+,0x8F03
+,0xFA10
+,0x8C15
+,0xA300
+,0x0089
+,0xA302
+,0x0086
+,0x8D10
+,0xBC25
+,0x201C
+,0x0061
+,0xFAB4
+,0xA301
+,0x0089
+,0x208C
+,0x8F07
+,0x2600
+,0x8F03
+,0xFA70
+,0x8C04
+,0xA300
+,0x0089
+,0xA302
+,0x0086
+,0xBC20
+,0x201F
+,0xBC21
+,0x03FF
+,0xFA10
+,0xA203
+,0x0089
+,0x0801
+,0x2258
+,0x8F03
+,0x8EC0
+,0xA302
+,0x0086
+,0x8E00
+,0x8EB8
+,0xBC20
+,0x201B
+,0x4381
+,0xFA10
+,0x0801
+,0xA201
+,0x0089
+,0xB480
+,0x0002
+,0xBC22
+,0x201C
+,0x0008
+,0xFA51
+,0x2001
+,0xA300
+,0x0089
+,0x8F03
+,0x8EC0
+,0x4020
+,0xA300
+,0x0086
+,0x8EB8
+,0xE902
+,0xBC22
+,0x2000
+,0xDFD5
+,0x41A3
+,0xBC02
+,0x0723
+,0x4344
+,0xBC25
+,0x0400
+,0x2620
+,0x8F05
+,0xBC02
+,0x07F0
+,0x5404
+,0x4025
+,0xBC02
+,0x07F0
+,0x8D06
+,0xBC02
+,0x07FB
+,0x5404
+,0x4025
+,0xBC02
+,0x07FB
+,0xBC02
+,0x072A
+,0x4E20
+,0xBC02
+,0x07B8
+,0xBC20
+,0x0001
+,0x0848
+,0xB412
+,0x0000
+,0xBC22
+,0x1000
+,0x4183
+,0xBC02
+,0x0723
+,0x220A
+,0x8F3F
+,0xDFE2
+,0xBC21
+,0x2098
+,0x41C2
+,0xFA33
+,0x0ADA
+,0xFB33
+,0x4060
+,0x4841
+,0xBC02
+,0x07D8
+,0xBC21
+,0x2098
+,0x4202
+,0xBC20
+,0xFFFE
+,0x0ADA
+,0xFB33
+,0x08D8
+,0xFB33
+,0x4E20
+,0xBC02
+,0x07B8
+,0xBC22
+,0xFFFE
+,0x084A
+,0xCFE2
+,0x0A4A
+,0xBC02
+,0x07CA
+,0x4224
+,0xBC25
+,0x4000
+,0xBC02
+,0x07FB
+,0x4044
+,0x4045
+,0xBC02
+,0x07FB
+,0x4284
+,0x4105
+,0xBC02
+,0x07FB
+,0x4284
+,0x4105
+,0xBC02
+,0x07F0
+,0xCFE0
+,0xBC02
+,0x0733
+,0x4E24
+,0x4045
+,0xBC02
+,0x07FB
+,0x4E24
+,0x4045
+,0xBC02
+,0x07F0
+,0xBC20
+,0x2098
+,0x43E1
+,0xFB11
+,0x4021
+,0xFB11
+,0xBC22
+,0x4000
+,0x41C3
+,0xBC02
+,0x0723
+,0x38A2
+,0x4E20
+,0xBC02
+,0x07B8
+,0xB55A
+,0x0002
+,0x0A4D
+,0xBC02
+,0x07CA
+,0xCFD5
+,0xE9FE
+,0x8EB8
+,0xBC20
+,0x201F
+,0x8E00
+,0xFA10
+,0x0890
+,0x1093
+,0x8EB8
+,0xE902
+,0x4E24
+,0xDFD5
+,0x4085
+,0xBC02
+,0x07FB
+,0xCFD5
+,0xE9FE
+,0x8EB8
+,0xE902
+,0xBC21
+,0x202D
+,0xDFD5
+,0xDFE0
+,0x4280
+,0xBC02
+,0x07CA
+,0xBC22
+,0x8018
+,0xBC23
+,0x8098
+,0xCFE0
+,0x2600
+,0x1853
+,0x42C0
+,0xBC02
+,0x07CA
+,0x4240
+,0xBC21
+,0xE419
+,0xBC02
+,0x07CA
+,0x4260
+,0xBC21
+,0x9010
+,0xBC02
+,0x07CA
+,0x4040
+,0xBC21
+,0x0FFB
+,0xBC02
+,0x07CA
+,0x4220
+,0xBC21
+,0x2020
+,0xBC02
+,0x07CA
+,0xBC20
+,0x0005
+,0x4461
+,0xBC02
+,0x07D8
+,0x4220
+,0xBC21
+,0x1020
+,0xBC02
+,0x07CA
+,0xBC20
+,0x0005
+,0x4461
+,0xBC02
+,0x07D8
+,0x4220
+,0xBC21
+,0x4020
+,0xBC02
+,0x07CA
+,0xBC20
+,0x0064
+,0x4461
+,0xBC02
+,0x07D8
+,0x4520
+,0xBC21
+,0x8001
+,0xBC02
+,0x07CA
+,0xCFD5
+,0xE9FE
+,0x8EB8
+,0xE902
+,0xBC20
+,0x2023
+,0xDFD5
+,0xFA16
+,0xBC20
+,0x2000
+,0x09B0
+,0xDFE6
+,0x4060
+,0xBC02
+,0x07B8
+,0xBC22
+,0x39AE
+,0xBC23
+,0x19AE
+,0xCFE6
+,0x2660
+,0x195A
+,0x220D
+,0x8F02
+,0x3825
+,0xBC02
+,0x07CA
+,0x4480
+,0xBC02
+,0x07B8
+,0xBC22
+,0x0000
+,0xBC23
+,0x0001
+,0xCFE6
+,0x2660
+,0x195A
+,0x220D
+,0x8F02
+,0x3825
+,0xBC02
+,0x07CA
+,0xCFD5
+,0xE9FE
+,0x8EB8
+,0xE902
+,0x4E04
+,0x4805
+,0xDFD5
+,0xBC20
+,0x2023
+,0xBC21
+,0x4000
+,0xFA10
+,0x0801
+,0x2600
+,0x8F01
+,0xBC02
+,0x07FB
+,0x8D02
+,0xBC02
+,0x07F0
+,0xCFD5
+,0xE9FE
+,0x8EB8
+,0xBC22
+,0x209A
+,0xBC23
+,0x0100
+,0x0AD8
+,0xBC21
+,0x209D
+,0xFB53
+,0x4043
+,0xFA32
+,0x0893
+,0x26A0
+,0x8FFA
+,0xBC22
+,0x209C
+,0x8E00
+,0xFA51
+,0x8EB8
+,0xBC22
+,0x209A
+,0xBC23
+,0x209B
+,0xFB50
+,0xBC22
+,0x209D
+,0xFB71
+,0x4023
+,0xFA51
+,0x084B
+,0x2690
+,0x8FFB
+,0x8EB8
+,0xBC08
+,0x07E6
+,0x8E00
+,0xBDC8
+,0x07E5
+,0x8E00
+,0xBC09
+,0x07E4
+,0x8E00
+,0x8E00
+,0x8E00
+,0x8E00
+,0x8E00
+,0x8E00
+,0x8E00
+,0x8EB8
+,0xBC08
+,0x07EE
+,0x8E00
+,0xBC09
+,0x07ED
+,0x8E00
+,0x8E00
+,0x8EB8
+,0xE902
+,0x3804
+,0xDFD5
+,0xBC02
+,0x07B8
+,0x0A4D
+,0xBC02
+,0x07CA
+,0xCFD5
+,0xE9FE
+,0x8EB8
+,0xE902
+,0x1745
+,0xDFD5
+,0x3804
+,0xBC02
+,0x07B8
+,0x084D
+,0xBC02
+,0x07CA
+,0xCFD5
+,0xE9FE
+,0x8EB8
+,0xBC20
+,0x201A
+,0x4201
+,0xFA10
+,0x0801
+,0x2600
+,0x8F00
+,0x8EB8
+,0xE902
+,0x4020
+,0xDFD5
+,0xBC21
+,0x1F2A
+,0xBC02
+,0x07CA
+,0xBC20
+,0x01F4
+,0x4461
+,0xBC02
+,0x07E8
+,0x4000
+,0xBC21
+,0x402D
+,0xBC02
+,0x07CA
+,0x4280
+,0x4461
+,0xBC02
+,0x07E8
+,0x4000
+,0xBC21
+,0x5FED
+,0xBC02
+,0x07CA
+,0x4020
+,0xBC21
+,0x1F6A
+,0xBC02
+,0x07CA
+,0x4280
+,0x4461
+,0xBC02
+,0x07E8
+,0x4000
+,0xBC21
+,0x7FED
+,0xBC02
+,0x07CA
+,0x4500
+,0x4461
+,0xBC02
+,0x07E8
+,0xBC20
+,0x2023
+,0xBC22
+,0x39AE
+,0xBC23
+,0x19AE
+,0xFA10
+,0xBC21
+,0x2000
+,0x0841
+,0x38C1
+,0x2610
+,0x185A
+,0x4060
+,0xBC02
+,0x07CA
+,0x4040
+,0xBC21
+,0x0FF9
+,0xBC02
+,0x07CA
+,0xBC20
+,0x000A
+,0x4461
+,0xBC02
+,0x07E8
+,0x4022
+,0x4003
+,0x2660
+,0x1853
+,0x4480
+,0xBC02
+,0x07CA
+,0x4540
+,0xBC02
+,0x07B8
+,0xDFE1
+,0x40C0
+,0x4202
+,0x41E3
+,0x4104
+,0xBC25
+,0x31EC
+,0x41E6
+,0xBC02
+,0x08EC
+,0x41C0
+,0xBC24
+,0x87FF
+,0x4166
+,0xBC02
+,0x08F9
+,0xCFE1
+,0x4000
+,0x4402
+,0x43E3
+,0x4164
+,0xBC25
+,0x31ED
+,0x43E6
+,0xBC02
+,0x08EC
+,0xDFE5
+,0x4180
+,0xBC24
+,0xFF07
+,0x4066
+,0xBC02
+,0x08F9
+,0xCFE5
+,0x40E0
+,0xBC24
+,0xFFE0
+,0x4006
+,0xBC02
+,0x08F9
+,0x4000
+,0xBC02
+,0x0733
+,0xBC20
+,0x2098
+,0x43E1
+,0xFB11
+,0x4021
+,0xFB11
+,0x4500
+,0x4401
+,0xBC02
+,0x07CA
+,0x4140
+,0xBC21
+,0x0841
+,0xBC02
+,0x07CA
+,0xBC20
+,0x01F4
+,0x4841
+,0xBC02
+,0x07E8
+,0x4140
+,0xBC21
+,0x0840
+,0xBC02
+,0x07CA
+,0x4500
+,0x4001
+,0xBC02
+,0x07CA
+,0xBC21
+,0x2023
+,0xBC22
+,0x0400
+,0xFA31
+,0x084A
+,0x2610
+,0x8F0A
+,0x5364
+,0x4065
+,0xBC02
+,0x07F0
+,0x4AC0
+,0x4021
+,0xBC02
+,0x07CA
+,0xBC21
+,0x1FFA
+,0x8D02
+,0xBC21
+,0x1FFB
+,0x4040
+,0xBC02
+,0x07CA
+,0x4C80
+,0x4841
+,0xBC02
+,0x07E8
+,0x41E0
+,0xBC21
+,0x4042
+,0xBC02
+,0x07CA
+,0xBC02
+,0x07A4
+,0x4E80
+,0x4021
+,0xBC02
+,0x07CA
+,0x4E60
+,0xBC21
+,0x0480
+,0xBC02
+,0x07CA
+,0x5380
+,0xBC21
+,0xAB40
+,0xBC02
+,0x07CA
+,0x4102
+,0x4503
+,0xBC24
+,0x2023
+,0xBC25
+,0x0400
+,0xFA94
+,0x0925
+,0x2640
+,0x1853
+,0x53C0
+,0xBC02
+,0x07CA
+,0x4E04
+,0x4025
+,0xBC02
+,0x07FB
+,0xCFD5
+,0xE9FE
+,0x8EB8
+,0x1048
+,0x0891
+,0x08D9
+,0x2620
+,0x1863
+,0xFAB2
+,0x004A
+,0x4002
+,0x3210
+,0x1851
+,0x210E
+,0x1971
+,0x8EB8
+,0xE901
+,0x8E00
+,0xDFF5
+,0xBC02
+,0x07B8
+,0x0861
+,0x316E
+,0x0A4D
+,0xBC02
+,0x07CA
+,0xCFF5
+,0xE9FF
+,0x8EB8
+,0xBC20
+,0x209F
+,0xBC21
+,0x31DB
+,0xA300
+,0x047E
+,0xA301
+,0x047D
+,0xBD11
+,0x0911
+,0xFA22
+,0xFB02
+,0x8EC0
+,0xA300
+,0x047E
+,0xA301
+,0x047D
+,0x0000
+,0x6915
+,0xA908
+,0xA21B
+,0x0180
+,0xA21E
+,0x017E
+,0xA21D
+,0x016E
+,0xBC3C
+,0x3116
+,0xBC30
+,0x311D
+,0x7016
+,0xDF1B
+,0xA204
+,0x017F
+,0xA202
+,0x0181
+,0xA203
+,0x0182
+,0xA201
+,0x01AD
+,0x6915
+,0x1F3D
+,0x77F6
+,0x9F5E
+,0xBC26
+,0x3106
+,0xDF70
+,0xDF9C
+,0xBD08
+,0x09DB
+,0xA200
+,0x015E
+,0xBC3C
+,0x009C
+,0xBC3E
+,0x00C2
+,0xA304
+,0x017F
+,0x6E7B
+,0x9FA1
+,0x6E43
+,0xBAC5
+,0x6E4B
+,0xBE18
+,0x396C
+,0x8A0E
+,0xBF95
+,0x8A18
+,0x77E6
+,0x9FC6
+,0x6A91
+,0x7AD5
+,0x7077
+,0xFE18
+,0x6A91
+,0x4F86
+,0x88D0
+,0x6E62
+,0xFAC7
+,0x6E7A
+,0x5FE0
+,0x39C8
+,0x8890
+,0xBC3D
+,0x0170
+,0x6FCA
+,0x4F41
+,0x6910
+,0xBAC5
+,0x6910
+,0xFF38
+,0x7016
+,0xBE38
+,0x2A47
+,0x6A91
+,0xFE38
+,0xBF95
+,0x8A38
+,0x6A91
+,0x7AC7
+,0xBF95
+,0x8A38
+,0xBF9D
+,0x8E38
+,0xBF95
+,0xAA38
+,0x2A47
+,0x6A91
+,0xFE38
+,0x2A45
+,0x88D0
+,0x398B
+,0x39E9
+,0x39C8
+,0x88F0
+,0xB06C
+,0xFFFA
+,0x613E
+,0xDF86
+,0xBC26
+,0x7ADD
+,0xBCB7
+,0x8000
+,0x04AA
+,0xBC26
+,0x7ADD
+,0xBCA5
+,0x8000
+,0xA300
+,0x015E
+,0x6025
+,0x0F00
+,0x6FCB
+,0xCFC4
+,0x6036
+,0x0FE0
+,0xB048
+,0xFFF1
+,0x6910
+,0xBF38
+,0x6910
+,0xDF41
+,0xFA86
+,0x6960
+,0x3E18
+,0x8A0E
+,0xBF99
+,0x0C18
+,0x7076
+,0x9F07
+,0x6A91
+,0xBA96
+,0x7016
+,0xBE18
+,0x2A46
+,0x88E0
+,0x398B
+,0x39E9
+,0x39C8
+,0x88F0
+,0xA300
+,0x015E
+,0x7077
+,0x8F20
+,0xBC3C
+,0x0160
+,0x6FCD
+,0xCF66
+,0x6910
+,0xBF18
+,0x6910
+,0xFAC7
+,0x7147
+,0xFE18
+,0x2A47
+,0xBF9D
+,0x8E18
+,0xBF9D
+,0x8E18
+,0x2A47
+,0xBF9D
+,0x8E18
+,0xBF9D
+,0x8E18
+,0xBF9D
+,0x8E18
+,0x2A47
+,0xBF9D
+,0xAE18
+,0x2A47
+,0x88F0
+,0xB06C
+,0xFFFA
+,0x6E62
+,0xDF66
+,0x39E9
+,0x39C8
+,0x88E0
+,0x0E7A
+,0x3F3E
+,0x63EC
+,0xFF18
+,0x6FC3
+,0x8FA1
+,0xBC3D
+,0x0184
+,0xB068
+,0xFFF1
+,0x6915
+,0xBF38
+,0x6915
+,0x1F20
+,0x5FDA
+,0x3885
+,0xCF1E
+,0xCF50
+,0xA310
+,0x017E
+,0xA301
+,0x01AD
+,0xA304
+,0x017F
+,0xA302
+,0x0181
+,0xA31E
+,0x0180
+,0xA303
+,0x0182
+,0xCF3B
+,0x8EC0
+,0xE9F8
+,0xA31B
+,0x016E
+,0x0000
+,0x2451
+,0xA201
+,0x01AC
+,0x3909
+,0xBC22
+,0x3124
+,0x2453
+,0xBC3D
+,0x0184
+,0x451F
+,0xBD08
+,0x0A11
+,0x77F6
+,0xFA43
+,0x2442
+,0x6960
+,0x3E38
+,0x8A0C
+,0xBF8C
+,0x8638
+,0x2A43
+,0x88B0
+,0x398B
+,0x39E9
+,0x39C8
+,0x88C0
+,0x439B
+,0x6E18
+,0x2403
+,0xB024
+,0xFFF3
+,0x6D06
+,0xA444
+,0x6910
+,0xEA38
+,0x8EC0
+,0xA301
+,0x01AC
+,0x8E00
+,0xBC20
+,0x3131
+,0xA201
+,0x02C2
+,0xFA10
+,0x2600
+,0x8F3E
+,0xA200
+,0x01E2
+,0x2680
+,0x8F39
+,0x2610
+,0xA200
+,0x01BE
+,0xB010
+,0xFFFF
+,0x8F2C
+,0xA202
+,0x01E3
+,0x26A0
+,0x8F28
+,0xBC22
+,0x02A8
+,0xBC23
+,0x3133
+,0xBC24
+,0x3132
+,0xBC40
+,0x3906
+,0xFA73
+,0xBC25
+,0x3134
+,0xBC27
+,0x3135
+,0xBC40
+,0x3102
+,0xFA94
+,0x04F3
+,0xFAB5
+,0xFAF6
+,0x04A2
+,0x1095
+,0x10DE
+,0x1D1A
+,0x4003
+,0x3240
+,0x3843
+,0x8F02
+,0xB228
+,0x0040
+,0x4803
+,0x18DC
+,0x2103
+,0x8F05
+,0x2183
+,0x8F18
+,0x3401
+,0xA300
+,0x01BE
+,0x8D15
+,0x8C14
+,0xA301
+,0x01BE
+,0x3280
+,0x4002
+,0x8F0D
+,0xA301
+,0x01BE
+,0x8D0C
+,0x8C0B
+,0x4002
+,0x2690
+,0x4800
+,0x4002
+,0x8F03
+,0x8E00
+,0x8C04
+,0xA302
+,0x01BE
+,0xA300
+,0x01BE
+,0xA200
+,0x01BE
+,0x2600
+,0xBC21
+,0x2035
+,0x4020
+,0x8EC0
+,0x1810
+,0xFB30
+,0x0000
+,0x38E0
+,0xA200
+,0x01E1
+,0xB202
+,0x0040
+,0x405A
+,0xBC3C
+,0x01C0
+,0x441E
+,0x8F0F
+,0x6E11
+,0xE800
+,0xBD08
+,0x0A88
+,0x6D74
+,0xA103
+,0xE142
+,0x1B1A
+,0x0E9A
+,0x3F14
+,0x6E11
+,0xFF18
+,0x8E00
+,0x8EC0
+,0xA300
+,0x01E1
+,0x8E00
+,0xB522
+,0x0009
+,0x3867
+,0xBD08
+,0x0A9D
+,0x6D76
+,0xA184
+,0xE1C3
+,0xBCB6
+,0x8000
+,0x8E00
+,0x1B63
+,0x0EE3
+,0x3F1D
+,0x6E19
+,0xFF18
+,0x8E00
+,0x8EC0
+,0xA300
+,0x01E1
+,0x8E00
+,0xA200
+,0x01F7
+,0x2600
+,0xA200
+,0x01E4
+,0x8F44
+,0xA201
+,0x01F8
+,0x2690
+,0x8F41
+,0xBC21
+,0x3173
+,0xA202
+,0x01E5
+,0xFA31
+,0x2191
+,0x8F02
+,0x3491
+,0xA302
+,0x01E5
+,0xA202
+,0x01E5
+,0x2251
+,0x8F33
+,0xBC21
+,0x02A8
+,0xBC23
+,0x316F
+,0xBC25
+,0x316C
+,0xBC40
+,0x4086
+,0xFA73
+,0xBC22
+,0x316D
+,0xBC24
+,0x316E
+,0x680C
+,0xFAB3
+,0xFA52
+,0xFA94
+,0x38A3
+,0x8F04
+,0xBC23
+,0x3170
+,0x8E00
+,0xFA73
+,0x2033
+,0x18D4
+,0xBC26
+,0x3171
+,0xBC40
+,0x4881
+,0xFAD6
+,0x210E
+,0x8F04
+,0xBC25
+,0x3172
+,0x8E00
+,0xFAB5
+,0x210D
+,0x1954
+,0x1E5D
+,0x2208
+,0x401E
+,0x8F0A
+,0x2108
+,0xA31E
+,0x01E5
+,0x8F03
+,0x8E00
+,0x8C05
+,0xB000
+,0xFFFF
+,0x3401
+,0x8D01
+,0x4000
+,0x40A1
+,0x2801
+,0xA300
+,0x01E4
+,0x382E
+,0xB012
+,0x3136
+,0xBC20
+,0x3163
+,0xBD04
+,0x0AFB
+,0xFA22
+,0xFB02
+,0xFA2A
+,0xFB02
+,0xBD04
+,0x0B01
+,0xFA2A
+,0xFB02
+,0x8EB8
+,0x0000
+,0x2451
+,0xA201
+,0x01E0
+,0x3909
+,0xBC22
+,0x3163
+,0x2453
+,0xBC3D
+,0x01C0
+,0x441F
+,0xBD08
+,0x0B25
+,0x77F6
+,0xFA43
+,0x2442
+,0x6960
+,0x3E38
+,0x8A08
+,0xBF8C
+,0x8638
+,0x2A43
+,0x88B0
+,0x398B
+,0x39E9
+,0x39C8
+,0x88C0
+,0x429B
+,0x6E18
+,0x2403
+,0xB024
+,0xFFF7
+,0x6D06
+,0xA444
+,0x6910
+,0xEA38
+,0x8EC0
+,0xA301
+,0x01E0
+,0x8E00
+,0xBC20
+,0x31B2
+,0x5FE1
+,0xFA10
+,0xB020
+,0x319C
+,0xB012
+,0x319C
+,0x0008
+,0xBC23
+,0x01F9
+,0xFA10
+,0xBC40
+,0x1981
+,0x6862
+,0x3A52
+,0xBC40
+,0x3582
+,0x8F06
+,0xA200
+,0x0085
+,0x2681
+,0x8F03
+,0x8EC0
+,0x4040
+,0xA300
+,0x0085
+,0x8EB8
+,0x0000
+,0xBC21
+,0x02A8
+,0xBC23
+,0x0263
+,0xBC40
+,0x4880
+,0xBC40
+,0x5084
+,0x6E10
+,0xE580
+,0x7000
+,0x25C4
+,0xA203
+,0x0266
+,0xBC40
+,0x5881
+,0x2630
+,0xBC40
+,0x1501
+,0x401C
+,0x8F28
+,0x3820
+,0xB532
+,0x0002
+,0xB036
+,0x3174
+,0x3882
+,0x6910
+,0xBA65
+,0x6960
+,0x2206
+,0x8A02
+,0xBBD4
+,0xCA86
+,0x6A3D
+,0x7A73
+,0x88C0
+,0x3215
+,0x00E3
+,0x8F05
+,0xB416
+,0x0002
+,0x0441
+,0x3214
+,0x1801
+,0x8C0A
+,0x3B80
+,0x3330
+,0x8F04
+,0x2614
+,0x8F04
+,0x8E00
+,0x8CE1
+,0x3449
+,0x344D
+,0x8DDE
+,0xBC20
+,0x31B2
+,0x383C
+,0xFA10
+,0x2108
+,0x1801
+,0xB000
+,0x319C
+,0x8EC0
+,0xFA10
+,0xA300
+,0x01FF
+,0xBC25
+,0x01F9
+,0x34AB
+,0xE904
+,0xE143
+,0x6122
+,0xDF82
+,0x3320
+,0x8F02
+,0xBC23
+,0x31B4
+,0x8C05
+,0xFA73
+,0xBC23
+,0x31B3
+,0x8E00
+,0xFA73
+,0x2813
+,0xA201
+,0x0260
+,0xBC40
+,0x268E
+,0xBC40
+,0x2E8F
+,0x6D4A
+,0xA29E
+,0x700E
+,0xE2DC
+,0x7307
+,0xDFDE
+,0x6E7F
+,0x224C
+,0xCFCE
+,0x6A34
+,0xDFA5
+,0x6E28
+,0x2800
+,0xBC3D
+,0x0200
+,0x6EE3
+,0xE287
+,0x88E0
+,0xBD07
+,0x0BC7
+,0x6D00
+,0x9FCE
+,0xBCFF
+,0x8000
+,0x8E00
+,0xE4E7
+,0xE2C5
+,0xBCDB
+,0x8000
+,0x6E7F
+,0x0FCE
+,0x6A34
+,0xE4E5
+,0x38A0
+,0x88E0
+,0x6EE3
+,0xE287
+,0xDFCE
+,0xBCFF
+,0x8000
+,0xCF82
+,0xE4E7
+,0xE2C5
+,0xBCDB
+,0x8000
+,0xE64C
+,0xE4E5
+,0xCFDF
+,0xE546
+,0xA301
+,0x0260
+,0xA31F
+,0x01F9
+,0xCFA3
+,0x8EC0
+,0xE9FC
+,0xE5DC
+,0x0000
+,0xBC22
+,0x31B7
+,0x8E00
+,0xFA52
+,0x26A0
+,0x8F04
+,0x8EC0
+,0xBC22
+,0x6568
+,0xA302
+,0x0268
+,0xA200
+,0x0261
+,0x403A
+,0xBC3C
+,0x0200
+,0x4C1E
+,0x8E00
+,0xE062
+,0xA300
+,0x0261
+,0x6904
+,0xBC1B
+,0x241B
+,0xBD1E
+,0x0BFA
+,0x67A6
+,0xBC1B
+,0x241B
+,0x1E9A
+,0xBC3D
+,0x0290
+,0xA201
+,0x0293
+,0x3B7A
+,0x407F
+,0xBC23
+,0x31B6
+,0x6EE7
+,0x64E2
+,0xFA73
+,0xA204
+,0x02B0
+,0xA300
+,0x0261
+,0xA301
+,0x0293
+,0x21A3
+,0x8F2C
+,0xA200
+,0x0293
+,0x407E
+,0xBC23
+,0x31B5
+,0x7016
+,0xBC1C
+,0x1EA2
+,0xB800
+,0xE61C
+,0x1EA2
+,0x1E93
+,0xB124
+,0x0001
+,0xBC23
+,0x2000
+,0xBCA4
+,0xC000
+,0xBC24
+,0x3FFF
+,0x24DA
+,0xB056
+,0xFFFF
+,0x3095
+,0x0562
+,0xA300
+,0x0293
+,0x4004
+,0xBD0B
+,0x0C39
+,0x33D0
+,0xB56A
+,0x0001
+,0x8F02
+,0xB548
+,0x0001
+,0x8C05
+,0x0172
+,0x3521
+,0x0572
+,0xB548
+,0x0001
+,0x8E00
+,0x30A3
+,0xA302
+,0x0269
+,0xA202
+,0x0269
+,0xA203
+,0x0268
+,0x0493
+,0x3220
+,0xBC23
+,0x0400
+,0x8F02
+,0xBC23
+,0x31B8
+,0x8E00
+,0xFA73
+,0xBC24
+,0x0267
+,0x281A
+,0xE643
+,0x8EC0
+,0xBC40
+,0x260F
+,0xBC40
+,0x1E0E
+,0x0000
+,0xBC23
+,0x0267
+,0x349D
+,0xE904
+,0x6D57
+,0xA15F
+,0x6D27
+,0xDF82
+,0x700E
+,0xA2DD
+,0xBC40
+,0x2184
+,0x6E7F
+,0x5FDF
+,0xBC40
+,0x1983
+,0x7307
+,0xA14C
+,0xCFCE
+,0x6AA7
+,0x1FA5
+,0xA200
+,0x0262
+,0xBC3C
+,0x0200
+,0x88E0
+,0x6EEB
+,0xFC1F
+,0x6960
+,0x1FCE
+,0xBC25
+,0x026F
+,0xBCFD
+,0xC000
+,0xBD07
+,0x0C8C
+,0xB51E
+,0x0002
+,0x6D7A
+,0xA681
+,0xE061
+,0xBC9C
+,0x4000
+,0x6E7F
+,0x4FCE
+,0xB512
+,0x0002
+,0x6AA7
+,0x26C1
+,0x88E0
+,0x6E29
+,0xDFCE
+,0x6EEB
+,0xFC1F
+,0xBCFD
+,0xC000
+,0x8E00
+,0xB51E
+,0x0002
+,0xE681
+,0xE061
+,0xBC9C
+,0x4000
+,0xCFA3
+,0xB512
+,0x0002
+,0xBC24
+,0x0267
+,0xE6C1
+,0xE5DD
+,0xE54C
+,0xA300
+,0x0262
+,0xBC40
+,0x0E06
+,0xCF85
+,0xCFDE
+,0x8EC0
+,0xE9FC
+,0xE6DE
+,0xA200
+,0x02A7
+,0x2600
+,0xBC01
+,0x0D4B
+,0xA203
+,0x0294
+,0x2630
+,0xA202
+,0x02C5
+,0xBC25
+,0x1000
+,0xA200
+,0x02C6
+,0xA204
+,0x02C3
+,0xA201
+,0x01BE
+,0xBCA5
+,0x4000
+,0xBC23
+,0x0294
+,0x8F33
+,0xBC26
+,0x31CE
+,0xBC40
+,0x1185
+,0x6990
+,0x7AD4
+,0x0495
+,0xBCA5
+,0x0000
+,0xBC26
+,0x31CF
+,0x00AA
+,0xBC25
+,0x31D0
+,0xBC40
+,0x1984
+,0xBC40
+,0x2187
+,0x0404
+,0xFAD6
+,0x044F
+,0xFAB5
+,0xBC81
+,0x8000
+,0xBC93
+,0x4000
+,0x0020
+,0x0079
+,0xA204
+,0x0299
+,0xBC40
+,0x1582
+,0xBC40
+,0x1D80
+,0xBC40
+,0x2581
+,0x8F07
+,0x32C0
+,0x4000
+,0x8F00
+,0xB008
+,0xFFFF
+,0x8C13
+,0xA300
+,0x0299
+,0xBC20
+,0x4000
+,0x21A0
+,0x8F00
+,0x3421
+,0x8C0B
+,0xA300
+,0x0299
+,0x403E
+,0xBC40
+,0x1D80
+,0xA31E
+,0x0294
+,0xBC40
+,0x2581
+,0xBC40
+,0x1582
+,0xBC20
+,0x31D1
+,0xBC40
+,0x1185
+,0xFA10
+,0x20A8
+,0x4020
+,0xBC40
+,0x1981
+,0x3840
+,0x8F06
+,0xBC20
+,0x31D2
+,0x8E00
+,0xFA10
+,0x2088
+,0x3802
+,0x8F00
+,0x4000
+,0xBC24
+,0x31D3
+,0xBC40
+,0x2183
+,0xFA94
+,0xBC27
+,0x31EE
+,0x4006
+,0x6867
+,0x3AF3
+,0x1932
+,0x202B
+,0x8F04
+,0xBC23
+,0x31EF
+,0x8E00
+,0xFA73
+,0x218B
+,0x8F00
+,0x3886
+,0x2640
+,0xBC21
+,0x029A
+,0x8F0B
+,0xBC23
+,0x31D4
+,0xA204
+,0x0299
+,0xFA73
+,0x2023
+,0x8F01
+,0x2600
+,0x8F03
+,0x8E00
+,0x8C13
+,0xA306
+,0x0295
+,0xBC20
+,0x31F7
+,0xBC40
+,0x2083
+,0xFA10
+,0x2118
+,0x1803
+,0xA302
+,0x0295
+,0xBC40
+,0x1C86
+,0xBC40
+,0x1486
+,0xBC40
+,0x5C86
+,0xBC40
+,0x2480
+,0xBC40
+,0x2080
+,0xB230
+,0x7530
+,0x4C02
+,0x8EC0
+,0x1810
+,0xBC40
+,0x2480
+,0x8EC0
+,0x4000
+,0xA300
+,0x0294
+,0x0000
+,0xBC22
+,0x31F0
+,0xE91C
+,0xBC24
+,0x029A
+,0x7007
+,0x3A52
+,0x6E11
+,0x1C82
+,0x6E7F
+,0x3C85
+,0xBC26
+,0x31F4
+,0xBC23
+,0x31F3
+,0x77FE
+,0xDCA4
+,0xBC27
+,0x31F2
+,0xB801
+,0xA891
+,0x7027
+,0xFA73
+,0xFAF6
+,0xDCC3
+,0xBC27
+,0x31D5
+,0xBC23
+,0x31DA
+,0xDD26
+,0xDD04
+,0xFAF6
+,0xBC24
+,0x31F5
+,0xFA73
+,0xDD66
+,0xDD43
+,0xFA96
+,0xB074
+,0x000B
+,0xBC23
+,0x31D8
+,0xDDA6
+,0xDD87
+,0xBC26
+,0x31D7
+,0xB800
+,0xE6F7
+,0xDCE1
+,0xBC24
+,0x31D6
+,0x6D34
+,0x9DC3
+,0xDDE7
+,0xBC21
+,0x8000
+,0xFAD6
+,0xBC27
+,0x31D9
+,0xFA94
+,0x6163
+,0x9E46
+,0xE1DE
+,0x6D34
+,0xDE03
+,0x6143
+,0x1E24
+,0xDE86
+,0xDE63
+,0xB801
+,0xEE73
+,0xB064
+,0x000C
+,0xBC21
+,0x31F6
+,0xDEA7
+,0xDEE3
+,0xDF06
+,0xBC27
+,0x31F1
+,0xB034
+,0x0009
+,0x6D45
+,0x1EC4
+,0xB800
+,0x6CD1
+,0x6E81
+,0xBAF6
+,0xB024
+,0x000A
+,0xDFA6
+,0xDF42
+,0xDF23
+,0xE1C3
+,0xE142
+,0xE246
+,0xDF64
+,0xDF8F
+,0xBC3D
+,0x029F
+,0xBD08
+,0x0E56
+,0x6CD8
+,0x1FC1
+,0x7003
+,0x0E27
+,0x6915
+,0xA044
+,0x8F01
+,0x2640
+,0x8F6F
+,0x6A3B
+,0xCCE5
+,0x6D6C
+,0x4EC7
+,0x6A3B
+,0xDFE6
+,0x88D0
+,0xB20C
+,0x0060
+,0xDCE5
+,0xCDC5
+,0x8F65
+,0x6A09
+,0x4D65
+,0x88FC
+,0x6910
+,0x8C86
+,0x28DD
+,0x28FD
+,0x8890
+,0xBCFF
+,0xC000
+,0xBC92
+,0x4000
+,0x2442
+,0x28D5
+,0x6A3F
+,0x4CE5
+,0x88F0
+,0x686B
+,0x8D26
+,0x611E
+,0x4DE7
+,0x2409
+,0x8F05
+,0xCFA6
+,0x686B
+,0x8CC5
+,0xCD06
+,0x666B
+,0x8CE5
+,0x6113
+,0x5DFC
+,0x2409
+,0x32F0
+,0xBCEC
+,0x4000
+,0x8F05
+,0xCD41
+,0x686E
+,0x5DFC
+,0x8F01
+,0x35F9
+,0xDDE7
+,0x686D
+,0x4EE6
+,0x401F
+,0x8F12
+,0x6CB8
+,0x0DC5
+,0x3BBC
+,0x8F09
+,0x38FE
+,0xBC21
+,0x2666
+,0xBCFE
+,0x4000
+,0xB06C
+,0xFFFF
+,0x3BA6
+,0x3BE7
+,0x0F27
+,0x6EF7
+,0xDEFD
+,0xBC3D
+,0x029F
+,0x8C26
+,0x409F
+,0xCDE5
+,0x69B4
+,0x0EA6
+,0x8F01
+,0x3569
+,0xDDE5
+,0x684B
+,0x9EFC
+,0x7027
+,0xCDC5
+,0xBC3D
+,0x029F
+,0x8F16
+,0x6910
+,0x8FC1
+,0x5BE5
+,0x28E5
+,0xBC25
+,0x31CA
+,0x403B
+,0xFAA6
+,0xE0E7
+,0x8A03
+,0xBBF9
+,0x4C3F
+,0x6A3F
+,0x9EF0
+,0x88D0
+,0x77FE
+,0xDFC1
+,0x66EB
+,0x0DC5
+,0x0F26
+,0x3BC6
+,0x8D02
+,0xDFE6
+,0xCDC5
+,0x6A09
+,0x4E47
+,0x88EC
+,0x6915
+,0x0F8F
+,0x6915
+,0x8E85
+,0x28F7
+,0x28DD
+,0x88B0
+,0xBC9D
+,0x8000
+,0xBCE6
+,0xC000
+,0x6915
+,0x0F8F
+,0x2456
+,0x6A33
+,0xCFC1
+,0x28D5
+,0x88A0
+,0x8E00
+,0x0556
+,0x242D
+,0x26D0
+,0x8F04
+,0xCFE6
+,0xCDA7
+,0x2137
+,0x19BE
+,0xDFE6
+,0x6D00
+,0xA444
+,0x6915
+,0xEA38
+,0xE4C4
+,0xCFE6
+,0xCF44
+,0xCF27
+,0xCF00
+,0xE7C3
+,0xE642
+,0xA305
+,0x029A
+,0xCE02
+,0xCD83
+,0xCF65
+,0xE441
+,0xCDE7
+,0xCE64
+,0xCEFB
+,0xCCF0
+,0xCCA1
+,0xE9E4
+,0xE6C6
+,0xE5C7
+,0xE55E
+,0x8EC0
+,0xE65B
+,0xE4D0
+,0xBC21
+,0x02A8
+,0xE90E
+,0x6E18
+,0x7C22
+,0xA204
+,0x02C4
+,0x6C28
+,0xA0C5
+,0xA200
+,0x02C2
+,0x6C49
+,0x5F04
+,0xB050
+,0x31BD
+,0x6E0D
+,0x1F55
+,0x6980
+,0x3AB6
+,0xB012
+,0xFFF2
+,0xA21E
+,0x02C6
+,0xB000
+,0x31BF
+,0x616C
+,0xA4DE
+,0x7000
+,0x5F21
+,0xFA12
+,0x4025
+,0x180D
+,0x0554
+,0xB020
+,0x31BB
+,0xA204
+,0x02C5
+,0xBC40
+,0x2187
+,0x31E7
+,0xFA52
+,0x0497
+,0xB000
+,0x31B9
+,0xBC40
+,0x1987
+,0x3127
+,0x6C88
+,0x3A10
+,0x0504
+,0x38F4
+,0xB00E
+,0xFFF7
+,0x6622
+,0x9F60
+,0x6D37
+,0x6446
+,0xB06E
+,0xFFF6
+,0x6C90
+,0x1F86
+,0x6643
+,0x2745
+,0xB05E
+,0xFFF5
+,0xB07E
+,0xFFF4
+,0xE1C6
+,0x6998
+,0x66C4
+,0xE7C2
+,0xDFC7
+,0xDFA5
+,0x8F54
+,0xBC20
+,0x02A8
+,0x700F
+,0x8E44
+,0x65E3
+,0x0EC5
+,0xB5A8
+,0x000F
+,0x65B3
+,0x65DE
+,0xBC40
+,0xBC02
+,0xBC40
+,0x5404
+,0xB4AA
+,0x0001
+,0xB5B6
+,0x000F
+,0xB4C8
+,0x0001
+,0xB5EC
+,0x000F
+,0x62B6
+,0x8EA2
+,0x0BB4
+,0x170A
+,0xBC40
+,0xC406
+,0xB4E4
+,0x0001
+,0xB5C8
+,0x000F
+,0xBC40
+,0x9403
+,0x62C9
+,0x8E83
+,0x178B
+,0xB4F6
+,0x0001
+,0xB5EC
+,0x000F
+,0x0BB7
+,0xBC40
+,0x8404
+,0xCEE4
+,0xB5FA
+,0x000F
+,0xBC40
+,0x4405
+,0x174C
+,0xBC40
+,0x8C07
+,0xB4F8
+,0x0001
+,0xB5DA
+,0x000F
+,0xBC40
+,0x3C02
+,0xBC40
+,0x4C03
+,0xB5A4
+,0x000F
+,0xB5B6
+,0x000F
+,0xBC40
+,0x3404
+,0x0B6F
+,0xB5C8
+,0x000F
+,0xBC40
+,0x7C02
+,0xBC40
+,0x9C03
+,0xBC40
+,0x5C01
+,0xBC40
+,0xAC01
+,0xBC40
+,0xB401
+,0xBC40
+,0x7405
+,0xBC40
+,0xA406
+,0x8C69
+,0xA304
+,0x02B5
+,0xBC23
+,0x02B5
+,0xBC22
+,0x31C4
+,0xB046
+,0xFFF9
+,0xFA52
+,0xDFE4
+,0xBC02
+,0x1E36
+,0x7000
+,0x4FE0
+,0xB030
+,0x000B
+,0xBC20
+,0x31C3
+,0xB046
+,0xFFF7
+,0xFA12
+,0xCF80
+,0xDF84
+,0xBC02
+,0x1E36
+,0x7000
+,0x4F80
+,0x6D31
+,0xCFA0
+,0xBC22
+,0x31C6
+,0xB046
+,0xFFF8
+,0xFA52
+,0xDF84
+,0xBC02
+,0x1E36
+,0x7000
+,0x4F80
+,0xB030
+,0x000C
+,0xBC20
+,0x31C5
+,0xB046
+,0xFFF6
+,0xFA12
+,0xCFC0
+,0xDF84
+,0xBC02
+,0x1E36
+,0x6E05
+,0x0F81
+,0xB032
+,0x000E
+,0xBC40
+,0x788F
+,0x7000
+,0x61CE
+,0xB040
+,0xFFF3
+,0x88D8
+,0xBC22
+,0x31C7
+,0xB066
+,0xFFF3
+,0xCF20
+,0xFA52
+,0xDE65
+,0xDF26
+,0xDF83
+,0xBC02
+,0x1E36
+,0xCF80
+,0xCF01
+,0xBC47
+,0xA803
+,0xBC47
+,0x5804
+,0x6112
+,0xCE7E
+,0x6C33
+,0x0F21
+,0x241B
+,0xBC47
+,0xA004
+,0x6847
+,0x24DE
+,0xDEE3
+,0x8F03
+,0xBC23
+,0x31C9
+,0x4001
+,0x8C05
+,0xFA72
+,0xBC23
+,0x31C8
+,0x4001
+,0xFA72
+,0xB030
+,0xFFFE
+,0xB046
+,0xFFF6
+,0xCF60
+,0xBC02
+,0x1E36
+,0xBC21
+,0x02A8
+,0xBC20
+,0x31C1
+,0xCF1E
+,0xBC40
+,0x4083
+,0xFA10
+,0xBC40
+,0x649E
+,0x2098
+,0x8F09
+,0xBC20
+,0x31C2
+,0xBC40
+,0x5083
+,0xFA10
+,0x6406
+,0x0F55
+,0x0018
+,0x8C03
+,0xBC40
+,0x5480
+,0xCF55
+,0x8E00
+,0x8EC0
+,0xE9F2
+,0x8E00
+,0xBC23
+,0x00A5
+,0xBC20
+,0x3054
+,0x6E10
+,0xE181
+,0xB800
+,0x2074
+,0x24A1
+,0xA201
+,0x045F
+,0x28C8
+,0x6911
+,0x2902
+,0xBC21
+,0x00A3
+,0x6E10
+,0x654E
+,0xBC24
+,0x2081
+,0xE085
+,0xBC26
+,0x2083
+,0xB801
+,0x2837
+,0x692F
+,0x65CF
+,0xDFC3
+,0xFAD3
+,0x28D8
+,0x2444
+,0xBC23
+,0x00A1
+,0x6E10
+,0xE54E
+,0xE185
+,0xE1C6
+,0x692D
+,0x64CF
+,0x28E0
+,0x2444
+,0xA200
+,0x00A0
+,0x7008
+,0xA54E
+,0x6220
+,0xA5CF
+,0xBC24
+,0x2080
+,0x26A0
+,0xFA94
+,0xBC22
+,0x00A7
+,0x8F0E
+,0x38A2
+,0x8E00
+,0xE286
+,0xE2C7
+,0x24BE
+,0xBC26
+,0x3055
+,0x8E00
+,0xFAD6
+,0x28E6
+,0x2444
+,0x8E00
+,0xA30E
+,0x00A7
+,0xE6CF
+,0xBC24
+,0x3053
+,0x8E00
+,0xFA94
+,0x2244
+,0x8F3A
+,0x7007
+,0x8FC4
+,0xA20E
+,0x00A5
+,0xE24F
+,0x88C8
+,0xA20E
+,0x00A1
+,0x690B
+,0x21CF
+,0x88B8
+,0xA20E
+,0x00A3
+,0xE0CF
+,0x8898
+,0xBC26
+,0x3056
+,0xE10E
+,0xFAD6
+,0x6807
+,0xA14F
+,0x88A8
+,0x8F10
+,0xBC26
+,0x3057
+,0x8E00
+,0xFAD6
+,0x200E
+,0x8F0A
+,0xBC26
+,0x3059
+,0x8E00
+,0xFAD6
+,0x212E
+,0x8F04
+,0xBC25
+,0x3058
+,0x8E00
+,0xFAB5
+,0x2095
+,0x8F03
+,0x8E00
+,0x8C06
+,0xA31E
+,0x008C
+,0x403E
+,0x8E00
+,0xA31E
+,0x008C
+,0x403C
+,0xA303
+,0x009C
+,0xA301
+,0x009D
+,0xA304
+,0x009E
+,0xA302
+,0x009F
+,0xA31C
+,0x008B
+,0xE9FE
+,0x8EC0
+,0x3401
+,0xA300
+,0x00A0
+,0x6C84
+,0xA904
+,0xFA13
+,0x6E0D
+,0x1FD5
+,0xBC22
+,0x3104
+,0xB002
+,0xFFFD
+,0xFA52
+,0xBC21
+,0x7FFF
+,0x6622
+,0xA443
+,0x40A1
+,0xBC23
+,0x02CE
+,0xBC24
+,0x045A
+,0xBC02
+,0x1E36
+,0xCFD5
+,0x8E00
+,0x8EC0
+,0xE9FC
+,0x8E00
+,0xE906
+,0xA202
+,0x02D3
+,0x6E0D
+,0x1F81
+,0xB012
+,0xFFFB
+,0x6988
+,0x5FA1
+,0xDFD5
+,0x8F04
+,0xBC20
+,0x2080
+,0x4021
+,0x8C0F
+,0xA301
+,0x02D3
+,0xFA11
+,0xBC02
+,0x1E46
+,0xA201
+,0x0474
+,0x1A41
+,0x7007
+,0x9F61
+,0xBC20
+,0x2080
+,0xA31E
+,0x02D3
+,0xFB11
+,0x7040
+,0x4F83
+,0xBC22
+,0x3104
+,0x6C8C
+,0xBA10
+,0xFA52
+,0xBC23
+,0x7FFF
+,0x6626
+,0x9F60
+,0xCFA0
+,0xBC23
+,0x02D1
+,0xBC24
+,0x045B
+,0xBC02
+,0x1E36
+,0xCFD5
+,0x8E00
+,0x8EC0
+,0xE9FA
+,0x8E00
+,0xE902
+,0xFA31
+,0xDFC0
+,0xDFF5
+,0xBC02
+,0x1E46
+,0xCFC1
+,0xDFC0
+,0xFA31
+,0xBC02
+,0x1E46
+,0xCFC1
+,0x1A48
+,0xA200
+,0x02D5
+,0xA202
+,0x045C
+,0x0E41
+,0x26A0
+,0xA301
+,0x02D5
+,0x8F06
+,0xBC21
+,0x2082
+,0x401E
+,0xA200
+,0x02D5
+,0xA31E
+,0x02D5
+,0xFB30
+,0x6D14
+,0x4FF5
+,0xE9FE
+,0x40E0
+,0x8EC0
+,0x0848
+,0xA301
+,0x045C
+,0x6C84
+,0xBA10
+,0xE904
+,0xB580
+,0x0002
+,0xA201
+,0x0474
+,0xB100
+,0x00BE
+,0xBC23
+,0x2081
+,0x66C2
+,0x1FD5
+,0xBC22
+,0x3104
+,0x6E2D
+,0x3B74
+,0xB00A
+,0xFFFD
+,0xFA52
+,0xBC23
+,0x7FFF
+,0x6626
+,0xA444
+,0x40C1
+,0xBC23
+,0x02D6
+,0xBC24
+,0x045D
+,0xBC02
+,0x1E36
+,0xCFD5
+,0x8E00
+,0x8EC0
+,0xE9FC
+,0x8E00
+,0xE904
+,0xFA10
+,0x6E08
+,0x1FC1
+,0xDFF5
+,0xBC02
+,0x1E46
+,0xA201
+,0x0474
+,0xBC22
+,0x3104
+,0x6692
+,0x0FC0
+,0xBC23
+,0x2083
+,0x6C80
+,0xBA52
+,0xBC24
+,0x7FFF
+,0x6E05
+,0x3B71
+,0x6628
+,0x9FA1
+,0xB000
+,0xFFFD
+,0x40E1
+,0xBC23
+,0x02D9
+,0xBC24
+,0x045E
+,0xBC02
+,0x1E36
+,0xCFF5
+,0x8E00
+,0x8EC0
+,0xE9FC
+,0x8E00
+,0x0000
+,0xBC21
+,0x00A9
+,0x4402
+,0xE083
+,0xE0C4
+,0x24A3
+,0xBC23
+,0x213F
+,0x8E00
+,0x6960
+,0x3A74
+,0x8A0E
+,0x6A38
+,0xBA74
+,0xB300
+,0x0044
+,0x28E2
+,0x8F0B
+,0x2600
+,0x8F04
+,0x2444
+,0x8EC0
+,0xA30E
+,0x00A9
+,0xE4CF
+,0x4000
+,0x8EC0
+,0xA300
+,0x00A9
+,0xE4C0
+,0x8880
+,0x8EC0
+,0x8E00
+,0xA300
+,0x045F
+,0xE904
+,0xBC21
+,0x2022
+,0x6E05
+,0x1FD5
+,0xA21C
+,0x047A
+,0xB000
+,0xFFFD
+,0xFA35
+,0x7000
+,0x6445
+,0xDFFC
+,0xBC22
+,0x0780
+,0xBC23
+,0x02DD
+,0xBC24
+,0x02DF
+,0xBC02
+,0x1E36
+,0xA201
+,0x02DF
+,0xA200
+,0x02DC
+,0xCFE2
+,0xA092
+,0x8000
+,0xB000
+,0xFFFF
+,0xA301
+,0x047A
+,0x2680
+,0xA300
+,0x02DC
+,0x8F34
+,0xBC20
+,0x304D
+,0xBC3E
+,0x0320
+,0xBC3A
+,0x7FFF
+,0xFA10
+,0xA202
+,0x047C
+,0xA31E
+,0x02DC
+,0xA31A
+,0x047A
+,0x21C8
+,0x8F14
+,0xBC20
+,0x304E
+,0xBC23
+,0x304F
+,0xFA10
+,0x6872
+,0x3A70
+,0x8F03
+,0x2048
+,0x8F01
+,0x26A0
+,0x8F05
+,0x21C8
+,0x8F0A
+,0x4000
+,0xA300
+,0x047C
+,0x8D07
+,0x4040
+,0x8C05
+,0xA300
+,0x047C
+,0x4020
+,0xA300
+,0x047C
+,0xA200
+,0x047C
+,0x2242
+,0x4000
+,0x8F02
+,0xA300
+,0x047B
+,0x8C07
+,0xCFD5
+,0x7008
+,0x0FD5
+,0x8C03
+,0xA300
+,0x047B
+,0xCFD5
+,0x8E00
+,0x8EC0
+,0xE9FC
+,0x8E00
+,0xBC20
+,0x2021
+,0xA201
+,0x047C
+,0x6984
+,0x3A12
+,0x8F1B
+,0x2611
+,0xB034
+,0xFFE0
+,0x8F10
+,0x2692
+,0x8F1B
+,0xBC21
+,0x3051
+,0x8E00
+,0xFA31
+,0x20D1
+,0x8F00
+,0xA026
+,0x4000
+,0x21D1
+,0x8F11
+,0xB024
+,0x0020
+,0xA0A4
+,0x4000
+,0x8D0E
+,0xBC21
+,0x3052
+,0x8E00
+,0xFA31
+,0x8C09
+,0xA026
+,0x4000
+,0xBC21
+,0x3050
+,0xB024
+,0x0020
+,0xFA31
+,0xA0A4
+,0x4000
+,0x8EC0
+,0xFB12
+,0x8E00
+,0x0000
+,0xBC22
+,0x3105
+,0xE902
+,0xA21C
+,0x0326
+,0x77FE
+,0xBA52
+,0x6EF0
+,0x9FDC
+,0xA200
+,0x0312
+,0xBC3C
+,0x02E0
+,0xBC22
+,0x30C2
+,0xBC23
+,0x8EE4
+,0xBC24
+,0x771E
+,0xBC25
+,0x88E2
+,0x403B
+,0x706F
+,0xE800
+,0xBD05
+,0x11DA
+,0x6E30
+,0xBC19
+,0x2442
+,0x6960
+,0x3AC7
+,0x8A08
+,0xBB3D
+,0x8E19
+,0x28CF
+,0xA207
+,0x0315
+,0xBC21
+,0x12EB
+,0xA206
+,0x0316
+,0x28F9
+,0x28F3
+,0xA307
+,0x0316
+,0x88F0
+,0x2442
+,0x28FC
+,0x28F5
+,0xA307
+,0x0315
+,0x417A
+,0x88E0
+,0xA207
+,0x0317
+,0x699C
+,0xEA18
+,0x2442
+,0x4001
+,0x8F00
+,0xB01E
+,0xFFFF
+,0x6A3C
+,0x4FC1
+,0x88E4
+,0xBC3D
+,0x0318
+,0x5FFA
+,0x7007
+,0x64E6
+,0xA206
+,0x0317
+,0x6998
+,0xDFC1
+,0x8F02
+,0x35B1
+,0x3BA6
+,0x8E00
+,0xA31D
+,0x0317
+,0xA300
+,0x0312
+,0xCFC2
+,0x8EC0
+,0xE9FE
+,0xA302
+,0x0326
+,0x0000
+,0xA200
+,0x0325
+,0xA201
+,0x0354
+,0xBC3D
+,0x0327
+,0x459F
+,0x403B
+,0xBC3C
+,0x0318
+,0x41BE
+,0xBC22
+,0x30CB
+,0xBD05
+,0x1200
+,0x5FFA
+,0x3862
+,0x6910
+,0xBC1D
+,0x6960
+,0x3A64
+,0x8A03
+,0xBBB0
+,0xC81D
+,0x28EC
+,0x88B0
+,0x40DA
+,0xE4E3
+,0xEA18
+,0xA300
+,0x0325
+,0xA200
+,0x0353
+,0x3B9D
+,0x459E
+,0xBC22
+,0x30CF
+,0x5FFA
+,0xA301
+,0x0354
+,0x6910
+,0xBA43
+,0xE064
+,0x8A27
+,0xBB8C
+,0x861C
+,0x403A
+,0x28E3
+,0x88A0
+,0xEA18
+,0x8EC0
+,0xA300
+,0x0353
+,0xA302
+,0x0355
+,0xBC25
+,0x0357
+,0xBC22
+,0x30F8
+,0x6E09
+,0x7CA4
+,0xB800
+,0xA6B6
+,0x24B4
+,0xA206
+,0x0356
+,0x33B0
+,0x4FE4
+,0xBC27
+,0x01FF
+,0x35B1
+,0x1927
+,0x09F4
+,0xBC24
+,0x0100
+,0x4806
+,0x1926
+,0xA206
+,0x0355
+,0x2670
+,0xA307
+,0x0356
+,0x243E
+,0x28FC
+,0x2444
+,0x4004
+,0x7008
+,0x64CE
+,0x6673
+,0x26CF
+,0x2670
+,0x8F2C
+,0xBC27
+,0x30F7
+,0xE2CF
+,0xFAF7
+,0x6CDC
+,0x26C4
+,0xA20E
+,0x0357
+,0xA304
+,0x0357
+,0x88D8
+,0x8F1C
+,0x3230
+,0x8F01
+,0xB036
+,0xFFFF
+,0xFB53
+,0xA202
+,0x0359
+,0x2620
+,0x8F0D
+,0x2622
+,0x4043
+,0x8F05
+,0xB20A
+,0x099A
+,0x189A
+,0xB22A
+,0x21EC
+,0x8C08
+,0x18A2
+,0xB22A
+,0x13D7
+,0x8C04
+,0x188A
+,0xB20A
+,0x17AE
+,0x188A
+,0x8C07
+,0xA302
+,0x0359
+,0xBC22
+,0x30F7
+,0xB03E
+,0xFFFF
+,0xFB53
+,0xA202
+,0x0359
+,0x144A
+,0x2442
+,0x28F1
+,0x8894
+,0x8EC0
+,0x8E00
+,0xE441
+,0xBC22
+,0x2131
+,0xBC23
+,0x00B0
+,0xBC24
+,0x2135
+,0x6915
+,0x3B53
+,0xFA93
+,0xBC22
+,0x2136
+,0xE4C3
+,0xB800
+,0xA210
+,0xBC80
+,0x4000
+,0x6915
+,0xE902
+,0xBC21
+,0x30F9
+,0xA203
+,0x035B
+,0xBC22
+,0x035C
+,0x6E73
+,0xFA31
+,0xBC24
+,0x30FA
+,0x28C1
+,0xA300
+,0x035B
+,0xFA94
+,0x6E08
+,0xBC40
+,0x6A37
+,0x2143
+,0x2A83
+,0x88C0
+,0xDFCE
+,0xDFEF
+,0xBC20
+,0x0A30
+,0xBC88
+,0x0000
+,0xCFCE
+,0xA300
+,0x035A
+,0xCFEF
+,0x2444
+,0xA203
+,0x035E
+,0xB580
+,0x0001
+,0x6000
+,0xE4CE
+,0xB000
+,0x2000
+,0xE54F
+,0xA300
+,0x035E
+,0xBC21
+,0x3244
+,0xBC80
+,0x4000
+,0xBC21
+,0x2111
+,0x8EC0
+,0xE9FE
+,0xFB30
+,0xBC22
+,0x3105
+,0xBC24
+,0x30FB
+,0xE906
+,0xA203
+,0x035A
+,0xBC25
+,0xF000
+,0xFA52
+,0xFA94
+,0xA21E
+,0x0314
+,0xA21C
+,0x015F
+,0x66BA
+,0xDF84
+,0xDFA2
+,0x7050
+,0xDF63
+,0xDFDC
+,0xDF5E
+,0xBC22
+,0x0CCD
+,0xBC24
+,0x2131
+,0xBC25
+,0x199A
+,0xBC3B
+,0x009C
+,0xBC3D
+,0x02E0
+,0xBD0A
+,0x131D
+,0xA206
+,0x035F
+,0x700E
+,0x8F67
+,0x63ED
+,0xCFBE
+,0xB47C
+,0x000E
+,0xB11E
+,0x0005
+,0xA200
+,0x0360
+,0x0E08
+,0x2810
+,0xB5FE
+,0x000E
+,0x380E
+,0x1BB7
+,0xB000
+,0x0400
+,0xBCF0
+,0xC000
+,0xA306
+,0x035F
+,0xBCED
+,0x4000
+,0x283A
+,0xA307
+,0x0360
+,0x888C
+,0xBC27
+,0x00B1
+,0x6EE7
+,0x7B97
+,0x606C
+,0x0F40
+,0xBC27
+,0x3244
+,0xBCED
+,0xC000
+,0x7016
+,0xBC1F
+,0x6EE6
+,0xDF40
+,0xBC20
+,0x2135
+,0xBC21
+,0x2111
+,0xFA10
+,0xBC8E
+,0x0000
+,0xFB36
+,0xB560
+,0x0001
+,0xCF80
+,0xBC8C
+,0x0000
+,0xBC3E
+,0x00C2
+,0x63E1
+,0x8FC0
+,0x3F3E
+,0xFF18
+,0xDFC0
+,0xCFC2
+,0xA302
+,0x015F
+,0xCF43
+,0x8EC0
+,0xE9FA
+,0xA303
+,0x0314
+,0xA203
+,0x0366
+,0x6D06
+,0x6044
+,0xBC22
+,0x0367
+,0xA203
+,0x0363
+,0x08C3
+,0xA206
+,0x0355
+,0x6E00
+,0xBC45
+,0xBCC9
+,0x8000
+,0x698C
+,0x2146
+,0x24B5
+,0xA205
+,0x0364
+,0x28E5
+,0x2444
+,0xA303
+,0x0366
+,0x7000
+,0x244E
+,0x7008
+,0xE54F
+,0x1918
+,0x2640
+,0x8F4A
+,0xE14F
+,0xA20E
+,0x0367
+,0xE540
+,0xA300
+,0x0367
+,0xBC22
+,0x3101
+,0xE0C1
+,0x2409
+,0xFA52
+,0x88C8
+,0x218A
+,0x240C
+,0x3840
+,0x8F0B
+,0xBC20
+,0x2004
+,0x8E00
+,0xFA10
+,0x2680
+,0x3802
+,0x8F04
+,0xBC20
+,0x3100
+,0x5FE4
+,0xFA10
+,0x2108
+,0x181C
+,0xA201
+,0x0369
+,0xA204
+,0x0365
+,0x3449
+,0x084C
+,0xBC24
+,0x30FE
+,0x2610
+,0xA301
+,0x0369
+,0xA201
+,0x0362
+,0xFA94
+,0x195A
+,0x0048
+,0x3340
+,0x8F12
+,0x2650
+,0x8F14
+,0xBC20
+,0x3103
+,0xA204
+,0x0361
+,0x69B0
+,0x3A10
+,0x8F02
+,0x2188
+,0x8C04
+,0x185A
+,0x0410
+,0x2088
+,0x1853
+,0xA301
+,0x0361
+,0x3822
+,0x8D05
+,0xBC20
+,0x30FE
+,0xB028
+,0xFFFF
+,0xFB12
+,0x8EC0
+,0xA301
+,0x0362
+,0x8E00
+,0x8EB8
+,0xBC20
+,0x303D
+,0x4021
+,0xFA10
+,0xA202
+,0x0462
+,0x1408
+,0x3491
+,0xB000
+,0xFFFF
+,0x0810
+,0x2680
+,0xA300
+,0x0462
+,0xA200
+,0x0460
+,0x8F36
+,0xBC23
+,0x3041
+,0xBC22
+,0x3040
+,0x6980
+,0x3A73
+,0xA204
+,0x045B
+,0xA21C
+,0x045A
+,0xFA52
+,0x8F06
+,0x21A3
+,0x8F02
+,0x387C
+,0x201A
+,0x8F07
+,0x4000
+,0x8D06
+,0x21A3
+,0x8F03
+,0x387C
+,0x219A
+,0x8F00
+,0x3801
+,0xBC22
+,0x3043
+,0x8E00
+,0xFA52
+,0x2620
+,0x8F17
+,0xA202
+,0x0465
+,0x26A0
+,0x8F12
+,0xBC22
+,0x2004
+,0x8E00
+,0xFA52
+,0x26A0
+,0x8F0C
+,0xBC22
+,0x303F
+,0xA203
+,0x045E
+,0xFA52
+,0x209A
+,0x8F05
+,0xBC22
+,0x303E
+,0xA203
+,0x045D
+,0xFA52
+,0x211A
+,0x8F00
+,0x4000
+,0xBC22
+,0x3044
+,0xA300
+,0x0460
+,0xFA50
+,0xA202
+,0x0463
+,0x2680
+,0x8F03
+,0x4000
+,0x8C42
+,0xA300
+,0x0461
+,0xBC20
+,0x2015
+,0xBC23
+,0x3048
+,0xFA10
+,0xFA73
+,0x2003
+,0x4000
+,0x3860
+,0x8F1A
+,0xBC20
+,0x2080
+,0xBC24
+,0x3046
+,0xFA10
+,0xFA94
+,0x2184
+,0x3803
+,0x8F07
+,0xBC20
+,0x3047
+,0xBC24
+,0x2015
+,0xFA10
+,0xFA94
+,0x2020
+,0x3803
+,0x8F08
+,0xBC20
+,0x2083
+,0xBC24
+,0x3045
+,0xFA10
+,0xFA94
+,0x2004
+,0x3803
+,0x8F00
+,0x3801
+,0x2680
+,0x8F02
+,0xBC20
+,0x304A
+,0x8C05
+,0xFA10
+,0xBC20
+,0x3049
+,0x8E00
+,0xFA10
+,0xBC24
+,0x304B
+,0x0E10
+,0xFA92
+,0x2102
+,0x8F04
+,0xBC22
+,0x304C
+,0x8E00
+,0xFA52
+,0x2002
+,0x1890
+,0x33A0
+,0x180B
+,0xA300
+,0x0461
+,0xBC20
+,0x3042
+,0xA201
+,0x0461
+,0xA203
+,0x0460
+,0xB512
+,0x0001
+,0xFA10
+,0xA302
+,0x0463
+,0x0059
+,0x2600
+,0x8F0A
+,0x2601
+,0x8F07
+,0x2602
+,0x4042
+,0x8F02
+,0x2603
+,0x8C04
+,0x1851
+,0x8C02
+,0x4001
+,0x4021
+,0xBC20
+,0x200D
+,0x8EC0
+,0x8E00
+,0xFB11
+,0xBC20
+,0x0375
+,0xBC21
+,0x0372
+,0xBC22
+,0x036A
+,0xBC3C
+,0x0376
+,0x700E
+,0xA0C1
+,0x70CF
+,0xA040
+,0xBC23
+,0x038F
+,0xBC09
+,0x1482
+,0x2442
+,0xE104
+,0xBC26
+,0x1180
+,0x6A39
+,0xA185
+,0xBC21
+,0xF2C0
+,0x6A3A
+,0x61C7
+,0x6A3F
+,0xA5A5
+,0xE584
+,0xE184
+,0xE185
+,0xBC21
+,0x1CF0
+,0x6A3A
+,0x61C7
+,0xBC21
+,0x8620
+,0x6A3E
+,0x65A5
+,0x88C0
+,0x2442
+,0x6A39
+,0xA584
+,0xBC21
+,0x0840
+,0x6A3A
+,0x6184
+,0x6A3F
+,0xA185
+,0xBC21
+,0x0A40
+,0x6A3A
+,0x61C7
+,0xBC21
+,0x8620
+,0x6A3E
+,0x65A5
+,0x88C0
+,0x8E00
+,0xE584
+,0xE464
+,0xBC23
+,0x038F
+,0xBC21
+,0x0375
+,0x8E00
+,0xE4C0
+,0x8EB8
+,0x0000
+,0xA202
+,0x0372
+,0xA203
+,0x0395
+,0x009A
+,0xB214
+,0x0014
+,0x8F16
+,0xB024
+,0xFFEC
+,0x5FC3
+,0x04DA
+,0x3B43
+,0xA200
+,0x0375
+,0xBC3C
+,0x0376
+,0x433E
+,0xBC23
+,0x305B
+,0x77F6
+,0xAA18
+,0x6910
+,0xBA64
+,0xE065
+,0x8A05
+,0xBBB0
+,0xC81D
+,0x4023
+,0x8880
+,0xA303
+,0x0373
+,0x8EC0
+,0xA302
+,0x0395
+,0x8E00
+,0xBC20
+,0x03BA
+,0xA203
+,0x03B9
+,0x6D20
+,0xA00E
+,0xB206
+,0x0080
+,0xE04F
+,0xE14C
+,0x8F36
+,0x88B0
+,0x40A4
+,0xB226
+,0x01B0
+,0x40C5
+,0x1925
+,0x401C
+,0xB226
+,0x06C0
+,0x7007
+,0xA45C
+,0x4083
+,0x6607
+,0x255E
+,0xA205
+,0x0396
+,0xA202
+,0x03BE
+,0xA31C
+,0x03B9
+,0xA31C
+,0x03BA
+,0x2268
+,0x8F03
+,0x8E00
+,0x8C03
+,0xB034
+,0xFFFF
+,0x34D1
+,0xA300
+,0x0396
+,0xA202
+,0x03BD
+,0xB236
+,0x000A
+,0x8F05
+,0xB226
+,0xFFF6
+,0x3B83
+,0x8F04
+,0x4002
+,0x401C
+,0x8D02
+,0x4022
+,0x401C
+,0x26A1
+,0x8F00
+,0x40A0
+,0xA31C
+,0x03BE
+,0xA302
+,0x03BD
+,0x8C0D
+,0xA300
+,0x0397
+,0x2421
+,0xBC25
+,0x1000
+,0x28E5
+,0x34D9
+,0xA303
+,0x03B9
+,0xA30E
+,0x03BA
+,0xE44F
+,0xE54C
+,0xA200
+,0x0397
+,0x3048
+,0xBC20
+,0x7E7E
+,0x8EC0
+,0xBC82
+,0x0000
+,0x8E00
+,0xBC22
+,0x2131
+,0xBC24
+,0x00B2
+,0x77F6
+,0xBB54
+,0xBC23
+,0x2135
+,0xBC22
+,0x2136
+,0x7087
+,0xBA73
+,0x6910
+,0xFA52
+,0xBCB2
+,0xC000
+,0xBCA2
+,0x8000
+,0xA200
+,0x03A6
+,0x3F1A
+,0xBC22
+,0x3060
+,0xBC3C
+,0x03A8
+,0x6910
+,0xBF10
+,0xE902
+,0xFA43
+,0x6960
+,0x3E18
+,0x8A06
+,0xBF8C
+,0x8618
+,0xBF8C
+,0xA410
+,0x2A42
+,0xBC23
+,0x03C4
+,0x88D0
+,0x6D26
+,0xA19E
+,0xBC27
+,0x03C7
+,0x6E62
+,0xE15A
+,0x6E7A
+,0x5FC2
+,0x6E72
+,0x21DC
+,0x88A0
+,0x6D4E
+,0xA38E
+,0xA206
+,0x03A5
+,0xA300
+,0x03A6
+,0x6998
+,0x23CF
+,0xE24C
+,0xDFE5
+,0x8F03
+,0x8E00
+,0x8C16
+,0xB06C
+,0xFFFF
+,0x88E0
+,0x39FC
+,0x39DE
+,0x399A
+,0x8880
+,0xBC21
+,0x2045
+,0x2442
+,0x7007
+,0xBB30
+,0xBC20
+,0x2046
+,0xBC21
+,0x305A
+,0x7009
+,0xBB16
+,0x7007
+,0x3A30
+,0x3B4C
+,0x15B0
+,0x240A
+,0x4020
+,0x28C8
+,0xBC21
+,0x03BF
+,0xE7CF
+,0xA30E
+,0x03C7
+,0xBCAA
+,0x8000
+,0xA306
+,0x03A5
+,0x690B
+,0x60C6
+,0x6E20
+,0x664C
+,0x6E7F
+,0x2482
+,0x6E77
+,0xA0C7
+,0x6E66
+,0xA4C6
+,0x6A3A
+,0x0FC1
+,0xBC20
+,0x3068
+,0x6915
+,0x24CC
+,0xA30E
+,0x03C4
+,0x6915
+,0xE5CF
+,0x6915
+,0xBA01
+,0x6A34
+,0x7A02
+,0x6A3C
+,0xBA02
+,0xBC40
+,0x1205
+,0x6A3E
+,0xBA02
+,0x6A3A
+,0xBA16
+,0xBC40
+,0x1A03
+,0x6A3A
+,0x8FE0
+,0x28DE
+,0x88A0
+,0xBC40
+,0x1E05
+,0xBC40
+,0x1602
+,0xBC23
+,0x28BE
+,0xA204
+,0x03C3
+,0xBCA4
+,0xC000
+,0xB038
+,0x4000
+,0x009A
+,0xA302
+,0x03C3
+,0xBC23
+,0x3244
+,0xBCA4
+,0xC000
+,0xBC23
+,0x2111
+,0x8EC0
+,0xE9FE
+,0xFB72
+,0xA200
+,0x0398
+,0x2457
+,0xBC22
+,0x306D
+,0x77FE
+,0xA441
+,0xBC3C
+,0x0399
+,0x7067
+,0xBA43
+,0x6E73
+,0xE800
+,0x6915
+,0x3C1C
+,0x8A0A
+,0xBB8C
+,0x861C
+,0xBB8C
+,0xA413
+,0x28DA
+,0xA300
+,0x0398
+,0x8EC0
+,0x8880
+,0x8E00
+,0xE902
+,0xA203
+,0x0372
+,0x6CAC
+,0x1FD5
+,0x8F06
+,0xBC20
+,0x036A
+,0xBC21
+,0x213E
+,0xBC0B
+,0x15CB
+,0xFA32
+,0xE402
+,0xBC02
+,0x1445
+,0xBC02
+,0x148A
+,0xA201
+,0x0372
+,0x41E3
+,0xA202
+,0x0373
+,0x0459
+,0x2621
+,0xA301
+,0x0372
+,0x8F07
+,0x26A2
+,0x8F1A
+,0xA200
+,0x0374
+,0xBC02
+,0x1AEC
+,0x4002
+,0x8D16
+,0x3820
+,0xBC02
+,0x14AE
+,0x3820
+,0xBC02
+,0x1504
+,0xA201
+,0x03B8
+,0x2610
+,0x8F04
+,0xB002
+,0xFFFF
+,0x4002
+,0x8C08
+,0xA300
+,0x03B8
+,0x3820
+,0xBC02
+,0x15A4
+,0xA300
+,0x0374
+,0x4042
+,0xCFD5
+,0x8E00
+,0x8EC0
+,0xE9FE
+,0xA302
+,0x0373
+,0x3E02
+,0xBC20
+,0x03E5
+,0x3820
+,0xE002
+,0xE003
+,0xE044
+,0xE402
+,0xE484
+,0xE042
+,0xE482
+,0x7008
+,0xA443
+,0xA200
+,0x03E4
+,0x0C10
+,0xA300
+,0x03E4
+,0x3E01
+,0x8EB8
+,0xBC20
+,0x30BF
+,0xA201
+,0x0447
+,0xFA10
+,0x6852
+,0x2902
+,0xBC22
+,0x30BB
+,0xBC23
+,0x30BD
+,0x18D3
+,0xA202
+,0x0449
+,0xFA64
+,0x3491
+,0x6835
+,0x3A73
+,0x8F65
+,0xA202
+,0x0448
+,0x2153
+,0x8F07
+,0x3449
+,0x3401
+,0xA080
+,0x4000
+,0x4002
+,0x8C5B
+,0xA300
+,0x0447
+,0xBC20
+,0x30C1
+,0xA201
+,0x03CF
+,0xBC22
+,0x30BA
+,0x6114
+,0x5FF5
+,0x701F
+,0x3A10
+,0x4023
+,0x6220
+,0xDFDC
+,0xB412
+,0x0001
+,0x2620
+,0x8F04
+,0x7000
+,0x5FC1
+,0xA301
+,0x03CB
+,0xA301
+,0x03CC
+,0xBC22
+,0x30C0
+,0xA201
+,0x03D6
+,0x3449
+,0xFA52
+,0x20CA
+,0xA301
+,0x03D6
+,0x8F19
+,0x4041
+,0x0801
+,0x2600
+,0x8F13
+,0x3E02
+,0x4000
+,0xA300
+,0x0099
+,0x3E01
+,0xBC20
+,0x2008
+,0xBC21
+,0xFF7F
+,0xFA12
+,0x0851
+,0x7008
+,0x3B11
+,0xBC02
+,0x05B3
+,0x7010
+,0x4FC0
+,0x8C05
+,0xA301
+,0x009A
+,0x8C02
+,0x4060
+,0xCFC0
+,0x3302
+,0x8F18
+,0x3541
+,0xBC21
+,0x1111
+,0x2829
+,0x3200
+,0x380E
+,0x8F0D
+,0x70F0
+,0x4FF5
+,0xBC22
+,0x2042
+,0xBC23
+,0x2041
+,0xBC24
+,0xEEEF
+,0xBC0D
+,0x1681
+,0xFB51
+,0x6008
+,0x3B70
+,0x8C06
+,0x4002
+,0x8C04
+,0x7000
+,0x8FF5
+,0x7000
+,0x8FF5
+,0xA302
+,0x0448
+,0x8EC0
+,0xE9FE
+,0xA302
+,0x0449
+,0xA200
+,0x03CE
+,0xB300
+,0x6600
+,0x4020
+,0x3820
+,0x8F00
+,0xA200
+,0x044A
+,0x2681
+,0xA300
+,0x044A
+,0x8F27
+,0xA200
+,0x03D2
+,0x2600
+,0xBC22
+,0x2044
+,0x4000
+,0x1801
+,0xFA53
+,0x0118
+,0xBC23
+,0x2043
+,0xFB54
+,0xFA72
+,0x0448
+,0x0091
+,0xA204
+,0x03D5
+,0xFB72
+,0xB5C8
+,0x0001
+,0x0061
+,0xA202
+,0x044C
+,0x004A
+,0xBC23
+,0x2042
+,0xA204
+,0x0448
+,0xA300
+,0x03D2
+,0xBC22
+,0x2041
+,0xA205
+,0x03CA
+,0x0020
+,0xFB71
+,0xA300
+,0x0448
+,0xFB55
+,0xBC00
+,0x1612
+,0x8EB8
+,0xA201
+,0x03D5
+,0x3312
+,0xA201
+,0x03CE
+,0x8F0A
+,0xB312
+,0x3F00
+,0x8F07
+,0xA202
+,0x03D4
+,0x224A
+,0x8F04
+,0x4001
+,0x7008
+,0x2441
+,0xA300
+,0x03D0
+,0x8EB8
+,0x2680
+,0xA200
+,0x03CF
+,0x8F0A
+,0xFA11
+,0xB312
+,0x0198
+,0x8F05
+,0xA201
+,0x03D3
+,0x1641
+,0x40A2
+,0x2E4A
+,0x8F00
+,0x3401
+,0x3402
+,0xBC21
+,0x30BB
+,0x2041
+,0x8F04
+,0x4000
+,0xA300
+,0x03D0
+,0xBC20
+,0x30B3
+,0xA201
+,0x03D0
+,0x2611
+,0x4001
+,0x8F00
+,0xFA11
+,0xA300
+,0x03CF
+,0x8EC0
+,0xB592
+,0x0006
+,0xA301
+,0x03CE
+,0x6EF5
+,0x6080
+,0xE906
+,0x7007
+,0x20C1
+,0xA204
+,0x03CE
+,0x6313
+,0x1F83
+,0x65B0
+,0x5FA2
+,0x65C0
+,0x1FE3
+,0x7000
+,0x9FC0
+,0x4020
+,0x4207
+,0x5FE6
+,0xBC23
+,0xC6C0
+,0xBC21
+,0x6E40
+,0x38A2
+,0xBC0F
+,0x1720
+,0x2F68
+,0x2F20
+,0x8F00
+,0x0D6B
+,0x2FB0
+,0x8F00
+,0x0D69
+,0x1785
+,0x3491
+,0x4044
+,0x6815
+,0x0FE4
+,0x4147
+,0x8FEE
+,0x6E1D
+,0x0FA2
+,0xB036
+,0xFFFB
+,0x69A8
+,0x5FE3
+,0x8F08
+,0xB42A
+,0x0006
+,0xBC23
+,0x03FF
+,0x0893
+,0xA31C
+,0x03D5
+,0xDF62
+,0xA302
+,0x03D2
+,0x7000
+,0x8F83
+,0xBC21
+,0x7F80
+,0x3882
+,0xBD10
+,0x174F
+,0x2E90
+,0x2F68
+,0x2FB0
+,0x8F0B
+,0x26B1
+,0x8F02
+,0x09E9
+,0x2670
+,0x8F03
+,0xBC26
+,0x6E40
+,0x0D6E
+,0x8C03
+,0x1785
+,0x3521
+,0x3491
+,0x8E00
+,0xCFA0
+,0x2601
+,0xBC20
+,0x03FF
+,0x8F27
+,0xB41A
+,0x0006
+,0x0808
+,0x2680
+,0x8F01
+,0x32C2
+,0x8F00
+,0x403C
+,0x26B0
+,0xDF7C
+,0x8F12
+,0xBC22
+,0x30B3
+,0x6E20
+,0x8FC3
+,0xBC21
+,0x30BB
+,0xBD04
+,0x1772
+,0xFA86
+,0x6881
+,0xBA86
+,0x8F01
+,0x2246
+,0x8F03
+,0x21E1
+,0x1914
+,0xA304
+,0x03CF
+,0x8E00
+,0x8D0B
+,0xCFC0
+,0x6330
+,0x8FE0
+,0xA305
+,0x03D4
+,0xA304
+,0x03D5
+,0xBC02
+,0x16C7
+,0x8D01
+,0xCFC3
+,0x6EAF
+,0x8F60
+,0xA303
+,0x03D3
+,0x8EC0
+,0xE9FA
+,0xA305
+,0x03D4
+,0xB022
+,0x3098
+,0xA200
+,0x03D2
+,0x6980
+,0x3A45
+,0x8F26
+,0x4343
+,0x0519
+,0x4003
+,0xBC0C
+,0x1799
+,0xFA46
+,0x0DAE
+,0x2246
+,0x8F01
+,0x3882
+,0x3803
+,0x8E00
+,0x2680
+,0x8F18
+,0x2610
+,0x4046
+,0x4022
+,0x1996
+,0x4205
+,0x3290
+,0x0569
+,0xA306
+,0x03D5
+,0x8F02
+,0x3250
+,0x8F00
+,0x14D5
+,0xBC21
+,0x30A9
+,0x044C
+,0x3210
+,0x8F01
+,0x1451
+,0x00D9
+,0xA201
+,0x03D3
+,0x0C4B
+,0xA301
+,0x03D3
+,0x8EC0
+,0xA300
+,0x03D2
+,0x8E00
+,0xE904
+,0xA201
+,0x03CC
+,0xA200
+,0x03CD
+,0x7000
+,0x9F81
+,0xB000
+,0xFFFF
+,0xA302
+,0x03CE
+,0x6984
+,0x1FB5
+,0x8F4C
+,0x2680
+,0x8F47
+,0xA201
+,0x03CF
+,0x344A
+,0xBC20
+,0x30BB
+,0x21C8
+,0xBC20
+,0x30B3
+,0x1841
+,0x6E18
+,0x9FC1
+,0xBC21
+,0x03D7
+,0xBC02
+,0x1700
+,0xA201
+,0x03CF
+,0x7000
+,0x8FC0
+,0xA204
+,0x0444
+,0x6882
+,0x1FC1
+,0x4023
+,0x8F06
+,0xB018
+,0xFFFF
+,0x6CC7
+,0x9FC0
+,0x6626
+,0x9FE1
+,0x8C20
+,0xDF82
+,0x3422
+,0x6CE1
+,0x1FE0
+,0x181A
+,0x2681
+,0xA300
+,0x03CB
+,0x8F15
+,0xBC20
+,0x0444
+,0x8A09
+,0xE402
+,0xFA31
+,0xA21E
+,0x03D3
+,0xB592
+,0x0006
+,0xA302
+,0x03D0
+,0xA303
+,0x03D1
+,0xA302
+,0x03D5
+,0xA302
+,0x03D2
+,0xA301
+,0x03CE
+,0xA31E
+,0x03CA
+,0xBC02
+,0x1690
+,0xCFE2
+,0xCFC1
+,0xA302
+,0x0444
+,0xA301
+,0x03CF
+,0x8C26
+,0x71A0
+,0x0F85
+,0x8C23
+,0xCF85
+,0x2600
+,0x4681
+,0x1848
+,0x7008
+,0x1FC1
+,0x2C48
+,0x401E
+,0xBC21
+,0x03D9
+,0xBC20
+,0x03D7
+,0xA31E
+,0x03CF
+,0x1848
+,0x3862
+,0xBC02
+,0x1700
+,0xA202
+,0x03CF
+,0x6988
+,0x0FC0
+,0x4025
+,0x8F09
+,0x0885
+,0x2620
+,0x4006
+,0x8F00
+,0xBC02
+,0x15FE
+,0xA306
+,0x0444
+,0x8C02
+,0x4680
+,0xCF85
+,0xCFB5
+,0xA305
+,0x03CC
+,0x8EC0
+,0xE9FC
+,0xA300
+,0x03CD
+,0xE902
+,0xA203
+,0x03CD
+,0xB036
+,0xFFFF
+,0x698C
+,0x1FC3
+,0xDFF5
+,0xBC01
+,0x190F
+,0xA201
+,0x03D1
+,0x2690
+,0xBC01
+,0x1920
+,0xB016
+,0xFFE6
+,0x4340
+,0x2048
+,0xBC01
+,0x190A
+,0xB306
+,0x0019
+,0xBC01
+,0x18F4
+,0xA201
+,0x03D2
+,0xB306
+,0x0018
+,0x8F7E
+,0xB306
+,0x0017
+,0x8F4E
+,0xCFC3
+,0xB316
+,0x0016
+,0xBC01
+,0x1920
+,0xA203
+,0x044B
+,0x26B0
+,0xBC01
+,0x1920
+,0x4023
+,0x2610
+,0xA303
+,0x044B
+,0x4002
+,0x8F0F
+,0xBC21
+,0x03D7
+,0xBC02
+,0x1700
+,0x2680
+,0xA300
+,0x03D2
+,0x8F07
+,0xA203
+,0x0444
+,0xA21E
+,0x03D3
+,0x34D9
+,0xA31E
+,0x03CA
+,0xA303
+,0x0444
+,0xA203
+,0x0444
+,0xB236
+,0x0080
+,0x8F19
+,0xA203
+,0x0446
+,0xB236
+,0x0080
+,0x7000
+,0xCFC5
+,0xBC21
+,0x0444
+,0x8F09
+,0xA200
+,0x0445
+,0xB200
+,0x0080
+,0x8F12
+,0x8A03
+,0xE483
+,0x3569
+,0xBC02
+,0x15FE
+,0x8D0D
+,0x8A03
+,0xE483
+,0xB05A
+,0xFFFF
+,0xBC02
+,0x15FE
+,0x8D06
+,0x7000
+,0xCFC5
+,0xBC21
+,0x0444
+,0x8A03
+,0xE483
+,0xA200
+,0x03D2
+,0xDFC5
+,0xBC02
+,0x16DA
+,0xBC02
+,0x1690
+,0x8D73
+,0x2610
+,0xBC21
+,0x03D7
+,0x8F24
+,0xBC40
+,0x1880
+,0x4023
+,0x2E03
+,0xBC40
+,0x1C80
+,0x4002
+,0x185A
+,0xA200
+,0x03D9
+,0x2E03
+,0x0001
+,0xA300
+,0x03D9
+,0xBC21
+,0x03D9
+,0x441A
+,0xBC02
+,0x1700
+,0x2680
+,0xA300
+,0x03D2
+,0x8F0B
+,0xA203
+,0x0445
+,0xA201
+,0x03D3
+,0x34D9
+,0xA301
+,0x03CA
+,0xA31A
+,0x044C
+,0xA303
+,0x0445
+,0x8C04
+,0x4003
+,0x8C02
+,0x4003
+,0x4003
+,0x8C47
+,0xA303
+,0x044B
+,0x2610
+,0xBC21
+,0x03D9
+,0x4002
+,0x4023
+,0x8F3D
+,0xBC02
+,0x1700
+,0x2680
+,0xA300
+,0x03D2
+,0x8F37
+,0xA203
+,0x0446
+,0x441E
+,0xA201
+,0x03D3
+,0x34D9
+,0xA301
+,0x03CA
+,0xA31E
+,0x044C
+,0xA303
+,0x0446
+,0x8D2C
+,0xA203
+,0x03D4
+,0x2630
+,0xBC20
+,0x03D2
+,0x8F00
+,0xBC02
+,0x16C7
+,0xA203
+,0x03D2
+,0x26B0
+,0x8F1E
+,0xA203
+,0x0444
+,0xA21E
+,0x03D3
+,0x34D9
+,0xA31E
+,0x03CA
+,0xA303
+,0x0444
+,0x8D16
+,0x4661
+,0x044B
+,0xBC02
+,0x1787
+,0x8D11
+,0xA200
+,0x03D7
+,0x4010
+,0x4023
+,0xA300
+,0x03CA
+,0xA310
+,0x03D1
+,0xBC21
+,0x03D7
+,0x3843
+,0xBC02
+,0x1700
+,0x4683
+,0xA310
+,0x044C
+,0xDFC3
+,0xCFF5
+,0xCFC3
+,0x8EC0
+,0xE9FE
+,0xA303
+,0x03CD
+,0xE902
+,0x8E00
+,0xDFD5
+,0x3E02
+,0xA200
+,0x03E3
+,0x7000
+,0x5FE0
+,0xA301
+,0x03E3
+,0x2600
+,0x8F12
+,0xA200
+,0x03CB
+,0x2680
+,0x8F02
+,0xA200
+,0x03CC
+,0x2600
+,0x8F02
+,0xA200
+,0x03CD
+,0x2681
+,0x8F06
+,0xBC20
+,0x03E5
+,0xBC21
+,0x03D7
+,0xBD04
+,0x1945
+,0xE002
+,0xE482
+,0x3E01
+,0x8C0E
+,0xCFE0
+,0xA200
+,0x03CB
+,0x2601
+,0x8F02
+,0xBC02
+,0x17B9
+,0x8C04
+,0xCFE0
+,0xBC02
+,0x183D
+,0xCFE0
+,0xB000
+,0xFFFF
+,0x69A0
+,0x1FE0
+,0x8FEF
+,0xCFD5
+,0x8E00
+,0x8EC0
+,0xE9FE
+,0x8E00
+,0xBC20
+,0x2048
+,0x8E00
+,0xFA10
+,0x2600
+,0x8F06
+,0xBC20
+,0x2043
+,0xBC22
+,0x2044
+,0x4001
+,0x8EC0
+,0xFB11
+,0xFB51
+,0x8EB8
+,0xA201
+,0x03E1
+,0xBC22
+,0x3079
+,0xFA20
+,0xB030
+,0xFFD8
+,0xB302
+,0x308C
+,0xA303
+,0x03EE
+,0x8EC0
+,0x1851
+,0xA301
+,0x03E1
+,0xA203
+,0x03E3
+,0x34D9
+,0xA200
+,0x03FD
+,0x5FFA
+,0xBC3C
+,0x03FA
+,0x407E
+,0xA303
+,0x03E3
+,0x7009
+,0x2461
+,0x6CE4
+,0x3C1E
+,0x4003
+,0xA205
+,0x03E4
+,0x19E3
+,0x0C95
+,0x2131
+,0x6555
+,0x2042
+,0x1863
+,0xA300
+,0x03FD
+,0x33A0
+,0xB05A
+,0x03E6
+,0x1823
+,0x637E
+,0x22C0
+,0x2E04
+,0xB5FE
+,0x0005
+,0x01C7
+,0x6678
+,0xE6A7
+,0x684C
+,0xA2C2
+,0x18E3
+,0x0C0B
+,0x2E94
+,0x8EC0
+,0x0097
+,0xE6C2
+,0xA200
+,0x03DB
+,0xBC3C
+,0x03DC
+,0x409E
+,0x405A
+,0xBC22
+,0x03EA
+,0x77FE
+,0xAA18
+,0xE05F
+,0xBC23
+,0x308C
+,0xE51F
+,0xBD03
+,0x19C3
+,0x6910
+,0xBC1C
+,0xFA65
+,0x8A03
+,0xBBB0
+,0xCA1C
+,0x28EC
+,0x88C0
+,0x8E00
+,0xE504
+,0x8EC0
+,0xEA18
+,0xA300
+,0x03DB
+,0xBC26
+,0x03E2
+,0xA202
+,0x03E9
+,0xE343
+,0x698C
+,0x2902
+,0xA203
+,0x03E0
+,0xBC01
+,0x1A6F
+,0xA204
+,0x03F6
+,0x69B0
+,0x5FD5
+,0x3883
+,0x8F02
+,0x4004
+,0xA304
+,0x03F6
+,0x3342
+,0x8F68
+,0xBC26
+,0x03F7
+,0x602D
+,0x215F
+,0x26C0
+,0xE55F
+,0x8F61
+,0x6E11
+,0xBCC5
+,0x6CF4
+,0x2341
+,0x4004
+,0x4026
+,0x19B4
+,0x3210
+,0x8F00
+,0x35B1
+,0xBC40
+,0x1102
+,0x3220
+,0x8F00
+,0x35B1
+,0x2663
+,0xA207
+,0x03F1
+,0x8F01
+,0x26E0
+,0x8F09
+,0x2435
+,0x2429
+,0x2412
+,0x20B5
+,0x8F00
+,0x35F9
+,0x2095
+,0x8F00
+,0xB07E
+,0xFFFF
+,0xA202
+,0x03F2
+,0x3551
+,0xB20A
+,0x004C
+,0x3844
+,0x8F0B
+,0xB23E
+,0x0008
+,0x38A7
+,0x4024
+,0x38E2
+,0x8F05
+,0x38E5
+,0x3378
+,0x3882
+,0x8F01
+,0x5FE4
+,0x38E2
+,0x38A2
+,0x00E3
+,0xA305
+,0x03F2
+,0xA307
+,0x03F1
+,0xDFE3
+,0xBC02
+,0x197C
+,0xA203
+,0x03F5
+,0xA202
+,0x03F3
+,0x6056
+,0x0FE4
+,0x3491
+,0xB438
+,0x0001
+,0xA305
+,0x03F5
+,0xB204
+,0x0208
+,0x8F14
+,0xA202
+,0x03F5
+,0xA205
+,0x03F4
+,0xB524
+,0x0001
+,0x20AA
+,0x401D
+,0x8F06
+,0xA202
+,0x03E4
+,0x4024
+,0x0C94
+,0x3883
+,0xA302
+,0x03E4
+,0x4643
+,0xA31D
+,0x03F5
+,0xA31D
+,0x03F4
+,0x4002
+,0xA303
+,0x03EF
+,0xA302
+,0x03F3
+,0xA202
+,0x03EF
+,0x2222
+,0x8F09
+,0x3491
+,0x2262
+,0x8F11
+,0xA202
+,0x03E9
+,0x8E00
+,0xE142
+,0xA302
+,0x03F0
+,0x8D0C
+,0xA201
+,0x03F0
+,0x7008
+,0x9FE4
+,0xBC02
+,0x197C
+,0xA202
+,0x03F4
+,0x6024
+,0x0FE4
+,0xA302
+,0x03F4
+,0xB008
+,0xFFFF
+,0x69A0
+,0x0FD5
+,0x8F79
+,0x700F
+,0xDFD5
+,0xBC02
+,0x196D
+,0xA31F
+,0x03F6
+,0xCFD5
+,0x8D73
+,0x7766
+,0xE145
+,0xA202
+,0x03F0
+,0x3822
+,0xBC3D
+,0x03F1
+,0x453F
+,0xA204
+,0x0442
+,0x69AC
+,0x64E5
+,0x6E28
+,0x6A38
+,0x8F02
+,0xA207
+,0x03EE
+,0x26F0
+,0x8F15
+,0xE142
+,0xE2C5
+,0x6175
+,0x60C2
+,0x615A
+,0xA242
+,0x243F
+,0x242D
+,0x017D
+,0xB05A
+,0x0008
+,0xB4DA
+,0x0004
+,0x356A
+,0xB4DA
+,0x0002
+,0x016A
+,0x206A
+,0x5FE2
+,0x1955
+,0x8C02
+,0xE605
+,0x5FE2
+,0xB006
+,0xFFFF
+,0x2680
+,0x8F3F
+,0xA203
+,0x0443
+,0x34D9
+,0xA303
+,0x0443
+,0xB236
+,0x00F0
+,0x8F08
+,0xDFC1
+,0xDFF5
+,0xBC24
+,0x041A
+,0xBC02
+,0x196D
+,0xCFF5
+,0x8C31
+,0xCFC1
+,0xBC24
+,0x041A
+,0x4003
+,0x6E38
+,0xE200
+,0x4005
+,0xA071
+,0xC000
+,0xBD27
+,0x1ABA
+,0x6659
+,0x6200
+,0xA071
+,0xC000
+,0x1965
+,0xA207
+,0x03EE
+,0xB0DA
+,0x041A
+,0x003D
+,0xB450
+,0x0001
+,0xA305
+,0x03EF
+,0x26D0
+,0x4685
+,0x4667
+,0x405F
+,0x19EF
+,0xE71F
+,0xA307
+,0x03CD
+,0xBC25
+,0x03F0
+,0x8A06
+,0xE703
+,0x8A0A
+,0xE683
+,0x8A03
+,0xE682
+,0xBC3F
+,0x03FA
+,0xA303
+,0x03CC
+,0xA31F
+,0x03FD
+,0xA303
+,0x03CB
+,0xA304
+,0x0442
+,0xA301
+,0x03F0
+,0xE9FE
+,0xA300
+,0x03E0
+,0xA202
+,0x03E9
+,0x8EC0
+,0x3491
+,0xA302
+,0x03E9
+,0x0000
+,0xE902
+,0xA201
+,0x03DB
+,0xDFD5
+,0x6960
+,0x24C0
+,0xBC02
+,0x19AA
+,0xBC20
+,0x03EA
+,0xA300
+,0x03E9
+,0xBD04
+,0x1AFD
+,0xBC02
+,0x19C8
+,0x8E00
+,0x8E00
+,0xCFD5
+,0x8E00
+,0x8EC0
+,0xE9FE
+,0x8E00
+,0xE902
+,0xA200
+,0x0466
+,0x6980
+,0x1FC0
+,0xBC01
+,0x1BB4
+,0xB310
+,0x00FF
+,0xBC01
+,0x1BBA
+,0xA201
+,0x0468
+,0xA202
+,0x0467
+,0xB034
+,0xFFFF
+,0x3310
+,0xBC20
+,0x0450
+,0xBC01
+,0x1BAA
+,0x3880
+,0x4021
+,0xE20E
+,0xE24F
+,0xBC24
+,0x3002
+,0x88D8
+,0xFA94
+,0xBCDB
+,0x0000
+,0xBC24
+,0x3009
+,0x2435
+,0xFA94
+,0x2134
+,0x4004
+,0x19CC
+,0xA307
+,0x0465
+,0xBC27
+,0x3013
+,0xA305
+,0x0464
+,0xFAF7
+,0x21B7
+,0x198C
+,0x26E0
+,0x8F04
+,0xBC26
+,0x2004
+,0x8E00
+,0xFAD6
+,0x2660
+,0x8F03
+,0xA206
+,0x046A
+,0x35B1
+,0xA306
+,0x046A
+,0xBC27
+,0x3011
+,0xA206
+,0x0469
+,0x35B1
+,0xFAF7
+,0x2037
+,0xA306
+,0x0469
+,0x8F0F
+,0xBC26
+,0x3012
+,0xA207
+,0x046A
+,0xFAD6
+,0x21BE
+,0x8F03
+,0x8E00
+,0x8C04
+,0xA304
+,0x046B
+,0xA301
+,0x046B
+,0xA304
+,0x046A
+,0xA304
+,0x0469
+,0xBC26
+,0x300A
+,0x8E00
+,0xFAD6
+,0x212E
+,0x0526
+,0x19B5
+,0x202C
+,0xBC25
+,0x2017
+,0x1926
+,0x6CA8
+,0x3AB2
+,0xBC25
+,0x3006
+,0x8F02
+,0xA303
+,0x0467
+,0xBC25
+,0x3003
+,0xBC23
+,0x300C
+,0x8E00
+,0xFA73
+,0x2013
+,0x8F13
+,0xBC26
+,0x300D
+,0x34E9
+,0xFAD6
+,0x2016
+,0x8F0C
+,0xBC26
+,0x300E
+,0x8E00
+,0xFAD6
+,0x2016
+,0x8F05
+,0xBC26
+,0x300F
+,0x8E00
+,0xFAD6
+,0x2016
+,0x8C02
+,0x18DD
+,0x34EA
+,0x38A3
+,0x2442
+,0xFAB2
+,0x28E2
+,0x88A0
+,0xBC23
+,0x300B
+,0xB524
+,0x0006
+,0xFA73
+,0xB424
+,0x0006
+,0x32B0
+,0x8F01
+,0x4003
+,0x049A
+,0xBC23
+,0x2020
+,0xB524
+,0x0001
+,0xFA73
+,0x0859
+,0x2690
+,0xBC23
+,0x2003
+,0x8F02
+,0x4001
+,0x8C0C
+,0xFB71
+,0x3451
+,0x8C09
+,0x7000
+,0x7B71
+,0xB012
+,0xFFFF
+,0xA301
+,0x0468
+,0xA303
+,0x0467
+,0x4001
+,0xE401
+,0xE441
+,0x8D06
+,0xBC20
+,0x2003
+,0x5FC1
+,0xFA12
+,0x0851
+,0xFB11
+,0xCFC0
+,0x3401
+,0xE9FE
+,0xBC21
+,0x00FF
+,0x8EC0
+,0x0801
+,0xA300
+,0x0466
+,0xE904
+,0xBC21
+,0x2016
+,0x6E05
+,0x1FD5
+,0xB000
+,0xFFFD
+,0xBC22
+,0x3000
+,0xFA31
+,0x7000
+,0x6441
+,0xFA52
+,0xBC23
+,0x044D
+,0xBC24
+,0x044F
+,0xBC02
+,0x1E36
+,0xA200
+,0x044F
+,0x7003
+,0x0FD5
+,0xBC22
+,0x4444
+,0x6915
+,0xE9FC
+,0x2456
+,0x28C2
+,0xBC20
+,0x3001
+,0x8890
+,0xBC22
+,0x0450
+,0x6910
+,0xBA10
+,0x28C8
+,0x6E00
+,0xBC41
+,0x88B4
+,0x7101
+,0x2145
+,0x24A9
+,0x28DC
+,0x2444
+,0x8EC0
+,0xE54F
+,0xE44E
+,0xBC21
+,0x3033
+,0xBC22
+,0x201E
+,0xB580
+,0x0001
+,0xFA31
+,0x4043
+,0xFA54
+,0x0923
+,0xB012
+,0xFFFF
+,0x2220
+,0x8F01
+,0x3310
+,0x8FF7
+,0x8EB8
+,0xA200
+,0x0470
+,0x3280
+,0xBC21
+,0x0477
+,0xBC22
+,0x0474
+,0x184A
+,0xA202
+,0x046D
+,0xBC40
+,0x1083
+,0x6CE8
+,0xE084
+,0x66B7
+,0x20C1
+,0x8F04
+,0xB044
+,0x3014
+,0x8E00
+,0xFA94
+,0x211C
+,0x8F0B
+,0x32A0
+,0xB044
+,0xFFFF
+,0x8F07
+,0xB058
+,0x3017
+,0x8E00
+,0xFAB5
+,0x219D
+,0x8F02
+,0x3844
+,0x8D01
+,0x3491
+,0xB034
+,0x301A
+,0xA302
+,0x046D
+,0xFA73
+,0xBC22
+,0x3023
+,0x1A59
+,0x2419
+,0xFA52
+,0x211A
+,0x8F05
+,0x3300
+,0x8F02
+,0xBC20
+,0x301F
+,0x8C05
+,0xFA10
+,0xBC20
+,0x301E
+,0x8E00
+,0xFA10
+,0x4202
+,0x0490
+,0xA203
+,0x0473
+,0x2442
+,0x28DA
+,0x28C8
+,0x8884
+,0xBC21
+,0x0200
+,0xBC90
+,0x4000
+,0xBC22
+,0x0800
+,0xBC80
+,0x8000
+,0xBC22
+,0x3024
+,0x2690
+,0x4004
+,0xA203
+,0x0454
+,0x1820
+,0xFA52
+,0x0E4B
+,0x210A
+,0xA300
+,0x0473
+,0x8F04
+,0xBC20
+,0x3025
+,0x8E00
+,0xFA10
+,0x2008
+,0x1881
+,0x8EC0
+,0xA302
+,0x0454
+,0x8E00
+,0xBC20
+,0x200F
+,0xA201
+,0x046E
+,0xFA10
+,0x2680
+,0x8F00
+,0x3449
+,0x2682
+,0x4000
+,0x8F00
+,0xB012
+,0xFFFF
+,0x3210
+,0x8F02
+,0x3317
+,0x40E0
+,0x1801
+,0x8EC0
+,0xA300
+,0x046E
+,0x8E00
+,0xBC20
+,0x3031
+,0xBC21
+,0x2000
+,0xFA12
+,0x0811
+,0x2241
+,0xA200
+,0x046E
+,0x8F03
+,0x4E00
+,0x0810
+,0xB400
+,0x0004
+,0xB010
+,0x3026
+,0xA203
+,0x0454
+,0xFA31
+,0xBC24
+,0x1000
+,0x0994
+,0x1AD9
+,0x2274
+,0x34D9
+,0x4025
+,0x111D
+,0x8F01
+,0x41E3
+,0x0913
+,0x4002
+,0x3240
+,0x3862
+,0x8F02
+,0x4103
+,0x2123
+,0x18DC
+,0xB5C6
+,0x0001
+,0xBC26
+,0x302E
+,0x0E4C
+,0x6980
+,0x3AD6
+,0xBC24
+,0x200B
+,0xB5F0
+,0x0004
+,0xA303
+,0x046F
+,0x1895
+,0x0E4E
+,0xA300
+,0x046E
+,0x00FB
+,0x6988
+,0x3B91
+,0x8F01
+,0x2681
+,0x8F00
+,0x4002
+,0x2620
+,0x8F01
+,0x2682
+,0x8F00
+,0x4002
+,0x2620
+,0x8F01
+,0x2683
+,0x8F00
+,0x4002
+,0x2620
+,0x8F40
+,0x2604
+,0x8F3E
+,0x2620
+,0x8F01
+,0x2685
+,0x8F00
+,0x4002
+,0x2620
+,0x8F33
+,0x2606
+,0x8F31
+,0x2620
+,0x8F01
+,0x2687
+,0x8F33
+,0xBC20
+,0x2005
+,0xBC21
+,0x0200
+,0xFA10
+,0x0801
+,0x2680
+,0x8F20
+,0xA200
+,0x0452
+,0x2602
+,0x8F11
+,0x2603
+,0x8F03
+,0x4060
+,0x8C25
+,0xA300
+,0x0452
+,0xBC20
+,0x3036
+,0xBC21
+,0x2081
+,0xFA10
+,0xFA31
+,0x2088
+,0x4040
+,0x8F18
+,0xA300
+,0x0452
+,0x8D17
+,0xBC20
+,0x3037
+,0xBC21
+,0x2081
+,0xFA10
+,0xFA31
+,0x2188
+,0x4060
+,0x8F0C
+,0xA300
+,0x0452
+,0x8D0B
+,0x4060
+,0xA300
+,0x0452
+,0x8D07
+,0x4020
+,0x8C05
+,0xA300
+,0x0452
+,0x4000
+,0xA300
+,0x0452
+,0xA200
+,0x0452
+,0xB000
+,0x3039
+,0xBC21
+,0x2006
+,0xFA10
+,0x8EC0
+,0x0003
+,0xFB30
+,0xA200
+,0x0474
+,0xA201
+,0x0453
+,0xB500
+,0x0007
+,0xBC22
+,0x302F
+,0x1AC8
+,0x241B
+,0xFA52
+,0x211A
+,0x8F02
+,0xBC22
+,0x3021
+,0x8C05
+,0xFA52
+,0xBC22
+,0x3020
+,0x8E00
+,0xFA52
+,0xA204
+,0x046C
+,0xBC23
+,0x8000
+,0x04DA
+,0x3340
+,0x2457
+,0x2456
+,0x8F04
+,0x2454
+,0x28CB
+,0x28C2
+,0x8C03
+,0x8880
+,0xA30E
+,0x046C
+,0xBC21
+,0x3030
+,0xBC22
+,0x3032
+,0xA300
+,0x0453
+,0xFA31
+,0xFA52
+,0xBC23
+,0x1000
+,0x0913
+,0x1A08
+,0xBC25
+,0x0400
+,0x2263
+,0xBC81
+,0x4000
+,0x8F01
+,0xBC20
+,0x0FFF
+,0x0810
+,0xBC21
+,0x200C
+,0x8EC0
+,0x8E00
+,0xFB30
+,0x0000
+,0xBC20
+,0x3022
+,0xBC21
+,0x3038
+,0x7017
+,0xBA10
+,0x700C
+,0x3A31
+,0xA310
+,0x046C
+,0xA31E
+,0x0470
+,0xA300
+,0x0454
+,0xA301
+,0x0452
+,0x6EE5
+,0x6800
+,0xBD0F
+,0x1D81
+,0xBC20
+,0x3034
+,0xBC21
+,0x2005
+,0xFA10
+,0xB000
+,0x0301
+,0x7008
+,0x3B30
+,0xBC02
+,0x1BF3
+,0xBC02
+,0x1C65
+,0xBC02
+,0x1C7B
+,0xBC20
+,0x3034
+,0xBC21
+,0x2005
+,0xFA10
+,0xB000
+,0x0201
+,0x7000
+,0x3B30
+,0xBC02
+,0x1BF3
+,0x8E00
+,0x8E00
+,0xBC20
+,0x3034
+,0xBC21
+,0x2005
+,0xFA10
+,0xB000
+,0x0301
+,0x7008
+,0x3B30
+,0xBC02
+,0x1BF3
+,0xBC02
+,0x1C65
+,0xBC02
+,0x1C7B
+,0xA201
+,0x046E
+,0xBC20
+,0x3034
+,0xB012
+,0x3026
+,0x6EAF
+,0x3A10
+,0xBC22
+,0x3035
+,0xBC23
+,0x2005
+,0xFA31
+,0xB000
+,0x0201
+,0xFA52
+,0xA301
+,0x0454
+,0xFB70
+,0xBC24
+,0x2009
+,0x8EC0
+,0x7008
+,0x3B72
+,0xFB90
+,0xE902
+,0xA200
+,0x0470
+,0x6CC0
+,0x1FD5
+,0x8F34
+,0xA200
+,0x0472
+,0xA201
+,0x0471
+,0x2680
+,0x8F0F
+,0xB312
+,0x007F
+,0xBC20
+,0x3035
+,0x8F07
+,0xFA10
+,0xB000
+,0x0101
+,0xBC21
+,0x2005
+,0x8C03
+,0x7008
+,0x3B30
+,0x4020
+,0x8C1E
+,0xA300
+,0x0472
+,0xB232
+,0x007F
+,0x4000
+,0x8F00
+,0x3409
+,0x3300
+,0xA300
+,0x0471
+,0x8F0A
+,0xBC02
+,0x1C65
+,0xBC02
+,0x1C7B
+,0xBC20
+,0x3035
+,0xBC21
+,0x2005
+,0xFA10
+,0x8C07
+,0x7000
+,0x3B30
+,0xBC02
+,0x1C04
+,0xBC02
+,0x1C7B
+,0x4000
+,0xA300
+,0x0472
+,0xBC02
+,0x1D12
+,0x8D13
+,0xBC02
+,0x1C04
+,0xBC02
+,0x1C7B
+,0xA200
+,0x0470
+,0xB000
+,0xFFFF
+,0xA201
+,0x0471
+,0xA300
+,0x0470
+,0xB232
+,0x007F
+,0x4000
+,0x8F00
+,0x3409
+,0xA300
+,0x0471
+,0x7008
+,0x4FD5
+,0xBC20
+,0x2009
+,0x8EC0
+,0xE9FE
+,0xFB11
+,0xBC21
+,0x2010
+,0xE908
+,0xBC20
+,0x200E
+,0xFA31
+,0xFA12
+,0xBC24
+,0x7F00
+,0x6E1D
+,0x1F95
+,0xB036
+,0xFFF9
+,0x0894
+,0xB444
+,0x0008
+,0x6E10
+,0xE581
+,0xFA10
+,0x73F8
+,0x65C4
+,0x0801
+,0xBC21
+,0x0474
+,0xBC40
+,0x1500
+,0xDFA1
+,0xBD03
+,0x1E2E
+,0xE0DC
+,0xE101
+,0xDFC2
+,0xDFFC
+,0xBC02
+,0x1E46
+,0xCFE1
+,0x63A0
+,0x4FA1
+,0x6D34
+,0x4FC2
+,0x6E20
+,0x6480
+,0xB406
+,0x0001
+,0xBC40
+,0x1E00
+,0xDFA1
+,0x7000
+,0x0F95
+,0xBC21
+,0x2009
+,0x8EC0
+,0xE9F8
+,0xFB30
+,0xE040
+,0x6C00
+,0x6246
+,0x6E08
+,0xE185
+,0x6681
+,0xA1C6
+,0x24B5
+,0x28C2
+,0x2444
+,0x8E00
+,0xE5CF
+,0x88B8
+,0x8EC0
+,0xE4CE
+,0xE643
+,0x3291
+,0x8F0C
+,0x24C1
+,0x1448
+,0x41A2
+,0x2442
+,0x4403
+,0x0410
+,0x28CB
+,0xB580
+,0x0004
+,0x8890
+,0x8EC0
+,0x0001
+,0x8E00
+,0x8EC0
+,0x4000
+,0x8E00
+,0xBC20
+,0x2092
+,0x4041
+,0xFA10
+,0xBC22
+,0x2093
+,0x0841
+,0x6984
+,0xBA51
+,0x8F0F
+,0x4022
+,0x0802
+,0x2681
+,0x8F17
+,0xBC20
+,0x2000
+,0x21C8
+,0xBC20
+,0x2095
+,0x8F02
+,0x8EC0
+,0xE0C1
+,0xFB11
+,0xFA31
+,0xFB11
+,0x8EB8
+,0xBC20
+,0x2094
+,0xBC22
+,0x2000
+,0x6872
+,0xBA10
+,0x8F02
+,0x8EC0
+,0xE4C0
+,0x8E00
+,0x8EC0
+,0xFB30
+,0x8E00
+,0x8EB8
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+};
+#endif
+
+const unsigned short bin_patch_E1[] = { 
+0x2000
+,0x21FF
+,0xBC24
+,0x20A0
+,0x8E00
+,0xFA95
+,0xB30A
+,0x06AF
+,0x8F2E
+,0xB30A
+,0x08E5
+,0x8F07
+,0xBC25
+,0x08E5
+,0xFB95
+,0xBC22
+,0x399E
+,0xBC23
+,0x199E
+,0xBC00
+,0x0841
+,0xBC25
+,0x06AF
+,0xFB95
+,0x5400
+,0xBC21
+,0xD0B1
+,0xBC02
+,0x07CA
+,0x5500
+,0xBC21
+,0x07C2
+,0xBC02
+,0x07CA
+,0x40A0
+,0xBC21
+,0x0359
+,0xBC02
+,0x07CA
+,0x41A0
+,0xBC21
+,0x00A0
+,0xBC02
+,0x07CA
+,0x41C0
+,0xBC21
+,0x4208
+,0xBC02
+,0x07CA
+,0x4380
+,0xBC21
+,0x2800
+,0xBC02
+,0x07CA
+,0x4E04
+,0xBC00
+,0x08E6
+,0x4344
+,0xBC25
+,0x0400
+,0x2620
+,0x8F06
+,0xBC02
+,0x07F0
+,0x5404
+,0x4025
+,0xBC02
+,0x07FB
+,0xBC00
+,0x06C1
+,0xBC02
+,0x07FB
+,0x5404
+,0x4025
+,0xBC02
+,0x07F0
+,0xBC00
+,0x06C1
+,0xBDC8
+,0x404E
+,0x8E00
+,0xFA11
+,0xBC00
+,0x0630
+,0x8E00
+,0x8E00
+,0x8E00
+,0xBC21
+,0x0002
+,0xBC20
+,0x2008
+,0xBC00
+,0x01BB
+,0xBC21
+,0x033F
+,0xA202
+,0x0083
+,0xFB11
+,0x8EA2
+,0xBC20
+,0x2008
+,0x7010
+,0x4FF5
+,0xBC22
+,0x201A
+,0xBC00
+,0x0161
+,0x4044
+,0xBC25
+,0x1000
+,0xBC02
+,0x07F0
+,0x4E24
+,0xBC00
+,0x0705
+,0xBC22
+,0x399E
+,0xBC23
+,0x199E
+,0xBC00
+,0x078A
+,0xBC24
+,0x2080
+,0x6C88
+,0x3A10
+,0xFA94
+,0xB548
+,0x0005
+,0xBC00
+,0x0E9F
+,0xE902
+,0xBC26
+,0x2023
+,0xDFE4
+,0xBC24
+,0x2000
+,0xFAD6
+,0x0934
+,0x26C0
+,0x8F01
+,0xBC26
+,0x3056
+,0x8D02
+,0xBC26
+,0x31F9
+,0xCFE4
+,0xE9FE
+,0xBC00
+,0x0FED
+,0xBC20
+,0x2090
+,0xBC21
+,0x0100
+,0xFA12
+,0xE902
+,0x0851
+,0x6984
+,0x1FD5
+,0x8F37
+,0x8E00
+,0x8D03
+,0x8E00
+,0xBC20
+,0x2090
+,0xBC21
+,0x8000
+,0xFA10
+,0x0801
+,0x2600
+,0x8FF5
+,0xBC20
+,0x2090
+,0xBC21
+,0x2091
+,0x714F
+,0xBA10
+,0xBC22
+,0x666D
+,0x7028
+,0xBB32
+,0x71F8
+,0xBB32
+,0xA203
+,0x0457
+,0x0802
+,0xA204
+,0x0458
+,0x6980
+,0x3B33
+,0xFB34
+,0xBC22
+,0x2545
+,0xA31E
+,0x0459
+,0xFB32
+,0x8F0C
+,0x2601
+,0x4FE1
+,0x8F0D
+,0x2602
+,0xBC21
+,0x0380
+,0x8F09
+,0x2683
+,0x4001
+,0x8F05
+,0xBC02
+,0x40E7
+,0x8D04
+,0xBC21
+,0x03FF
+,0xA301
+,0x0456
+,0xA301
+,0x0455
+,0xA200
+,0x0458
+,0xA201
+,0x0457
+,0x260F
+,0x8F02
+,0x8E00
+,0x8C03
+,0x3401
+,0x3449
+,0x4000
+,0xCFD5
+,0xA300
+,0x0458
+,0x8EC0
+,0xE9FE
+,0xA301
+,0x0457
+,0xBC22
+,0x3105
+,0xA200
+,0x0313
+,0x77DE
+,0xBA52
+,0x3BC2
+,0xBC22
+,0x2091
+,0xBC3C
+,0x02E0
+,0xBC23
+,0x666D
+,0x7000
+,0xFB53
+,0x700E
+,0xAA18
+,0xBC24
+,0x0B12
+,0xFB54
+,0x6D36
+,0x7C1C
+,0x6C8D
+,0x7B54
+,0x8FF9
+,0xA203
+,0x0355
+,0xFB53
+,0xA203
+,0x035A
+,0xFB53
+,0xA203
+,0x0464
+,0xBC24
+,0x2004
+,0xFB53
+,0xFA94
+,0xA203
+,0x047F
+,0xFB54
+,0xFB53
+,0xA204
+,0x0480
+,0xFB54
+,0xA203
+,0x0481
+,0xFB53
+,0xA204
+,0x0361
+,0xA203
+,0x0362
+,0xFB54
+,0xFB53
+,0xBC23
+,0x5A5A
+,0xFB53
+,0x8EC0
+,0xBC23
+,0x2545
+,0xFB53
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+};
+
+const unsigned short bin_patch_E2[] = { 
+0x2000
+,0x21FF
+,0x8E00
+,0x8E00
+,0x8E00
+,0xBC21
+,0x0002
+,0xBC20
+,0x2008
+,0xBC00
+,0x01A9
+,0xBC21
+,0x033F
+,0xA202
+,0x0083
+,0xFB11
+,0x8EA2
+,0xBC20
+,0x2008
+,0x7010
+,0x4FF5
+,0xBC22
+,0x201A
+,0xBC00
+,0x014F
+,0x240C
+,0xA301
+,0x047F
+,0xA30F
+,0x0480
+,0xA30E
+,0x0481
+,0xBC00
+,0x1353
+,0x5380
+,0xBC21
+,0xAC40
+,0xBC02
+,0x07EA
+,0x4380
+,0xBC21
+,0x2C00
+,0xBC02
+,0x07EA
+,0x43A0
+,0xBC21
+,0xFB40
+,0xBC02
+,0x07EA
+,0x43C0
+,0xBC21
+,0x0546
+,0xBC02
+,0x07EA
+,0x43E0
+,0xBC21
+,0xFB3C
+,0xBC02
+,0x07EA
+,0x4400
+,0xBC21
+,0x0537
+,0xBC02
+,0x07EA
+,0x4E04
+,0xBC00
+,0x092A
+,0x4025
+,0xBC21
+,0x2023
+,0xBC22
+,0x0400
+,0xFA31
+,0x084A
+,0x2610
+,0x8F01
+,0xBC02
+,0x081B
+,0x8D02
+,0xBC02
+,0x0810
+,0x4E24
+,0xBC00
+,0x0722
+,0x4280
+,0xBC02
+,0x07EA
+,0xBC22
+,0x8018
+,0xBC23
+,0x8098
+,0xCFE0
+,0x2600
+,0x1853
+,0x42C0
+,0xBC02
+,0x07EA
+,0x4240
+,0xBC21
+,0xE400
+,0xBC02
+,0x07EA
+,0x4260
+,0xBC21
+,0x0010
+,0xBC02
+,0x07EA
+,0x4040
+,0xBC21
+,0x0FFB
+,0xBC02
+,0x07EA
+,0x4220
+,0xBC21
+,0x2020
+,0xBC02
+,0x07EA
+,0xBC20
+,0x0005
+,0x4461
+,0xBC02
+,0x07F8
+,0x4220
+,0xBC21
+,0x1020
+,0xBC02
+,0x07EA
+,0xBC20
+,0x0005
+,0x4461
+,0xBC02
+,0x07F8
+,0x4220
+,0xBC21
+,0x4020
+,0xBC02
+,0x07EA
+,0xBC20
+,0x0064
+,0x4461
+,0xBC02
+,0x07F8
+,0x4240
+,0xBC21
+,0xE407
+,0xBC02
+,0x07EA
+,0x4260
+,0xBC21
+,0x7010
+,0xBC02
+,0x07EA
+,0xBC20
+,0x0064
+,0x4461
+,0xBC02
+,0x07F8
+,0x4520
+,0xBC21
+,0x8001
+,0xBC02
+,0x07EA
+,0xBC00
+,0x0794
+,0xBC20
+,0x2090
+,0xBC21
+,0x0100
+,0xFA12
+,0xE902
+,0x0851
+,0x6984
+,0x1FD5
+,0x8F37
+,0x8E00
+,0x8D03
+,0x8E00
+,0xBC20
+,0x2090
+,0xBC21
+,0x8000
+,0xFA10
+,0x0801
+,0x2600
+,0x8FF5
+,0xBC20
+,0x2090
+,0xBC21
+,0x2091
+,0x714F
+,0xBA10
+,0xBC22
+,0x666D
+,0x7028
+,0xBB32
+,0x71F8
+,0xBB32
+,0xA203
+,0x045B
+,0x0802
+,0xA204
+,0x045C
+,0x6980
+,0x3B33
+,0xFB34
+,0xBC22
+,0x2545
+,0xA31E
+,0x045D
+,0xFB32
+,0x8F0C
+,0x2601
+,0x4FE1
+,0x8F0D
+,0x2602
+,0xBC21
+,0x0380
+,0x8F09
+,0x2683
+,0x4001
+,0x8F05
+,0xBC02
+,0x40F6
+,0x8D04
+,0xBC21
+,0x03FF
+,0xA301
+,0x045A
+,0xA301
+,0x0459
+,0xA200
+,0x045C
+,0xA201
+,0x045B
+,0x260F
+,0x8F02
+,0x8E00
+,0x8C03
+,0x3401
+,0x3449
+,0x4000
+,0xCFD5
+,0xA300
+,0x045C
+,0x8EC0
+,0xE9FE
+,0xA301
+,0x045B
+,0xBC22
+,0x3105
+,0xA200
+,0x0314
+,0x77DE
+,0xBA52
+,0x3BC2
+,0xBC22
+,0x2091
+,0xBC3C
+,0x02E1
+,0xBC23
+,0x666D
+,0x7000
+,0xFB53
+,0x700E
+,0xAA18
+,0xBC24
+,0x0B12
+,0xFB54
+,0x6D36
+,0x7C1C
+,0x6C8D
+,0x7B54
+,0x8FF9
+,0xA203
+,0x0356
+,0xFB53
+,0xA203
+,0x035D
+,0xFB53
+,0xA203
+,0x0468
+,0xBC24
+,0x2004
+,0xFB53
+,0xFA94
+,0xA203
+,0x0483
+,0xFB54
+,0xFB53
+,0xA204
+,0x0484
+,0xFB54
+,0xA203
+,0x0485
+,0xFB53
+,0xA204
+,0x0364
+,0xA203
+,0x0365
+,0xFB54
+,0xFB53
+,0xBC23
+,0x5A5A
+,0xFB53
+,0x8EC0
+,0xBC23
+,0x2545
+,0xFB53
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+};
+
+const unsigned short bin_coeff_E1[] = { 
+0x0000
+,0x01FF
+,0x0400
+,0x0006
+,0x2AAB
+,0x0324
+,0x0324
+,0x0324
+,0x010C
+,0x010C
+,0x010C
+,0x1111
+,0x1259
+,0x0001
+,0x005A
+,0x0E9B
+,0x0FFF
+,0x0FFF
+,0x0008
+,0x0001
+,0x0001
+,0x0CCD
+,0xFFE0
+,0xFFD8
+,0x00FF
+,0xFFAC
+,0xFFBC
+,0xFF00
+,0x0020
+,0x0048
+,0x0050
+,0x0050
+,0x000E
+,0x0002
+,0x7000
+,0x0800
+,0xFFF8
+,0x0008
+,0x002B
+,0xFFF6
+,0xFFF8
+,0xFFFE
+,0x0003
+,0x0008
+,0x000D
+,0x000F
+,0x0014
+,0x0019
+,0x0000
+,0x0800
+,0x6580
+,0x0000
+,0x0000
+,0x7FFF
+,0x0008
+,0x0078
+,0xFEF5
+,0xFEE8
+,0x0003
+,0x0080
+,0x0080
+,0x0080
+,0x0300
+,0x0006
+,0xC080
+,0xF000
+,0x0660
+,0xDA80
+,0x0000
+,0x0001
+,0x0001
+,0xFFE4
+,0xFFE8
+,0x0080
+,0x0034
+,0x0001
+,0xFFFF
+,0x0001
+,0xFFFE
+,0x3AC0
+,0x3340
+,0x2BC0
+,0x07C0
+,0x05C0
+,0x03E0
+,0x0008
+,0x1000
+,0x2000
+,0xFF01
+,0xFFE5
+,0xFFE9
+,0x0DA8
+,0x000E
+,0xF75E
+,0x1136
+,0xEC7B
+,0x0D3C
+,0xFA9A
+,0xFC47
+,0xF58B
+,0x1055
+,0x3DDA
+,0x3DDA
+,0x1055
+,0xF58B
+,0xFC47
+,0x1B17
+,0x362A
+,0x1B17
+,0x67DA
+,0xA798
+,0xFDA6
+,0xF8BE
+,0xF36E
+,0xF0D4
+,0xF368
+,0xFB18
+,0x04E8
+,0x0C98
+,0x0F2C
+,0x0C92
+,0x0742
+,0x025A
+,0x0028
+,0x0029
+,0x0028
+,0x0029
+,0x0028
+,0x0029
+,0x0028
+,0x0028
+,0x0029
+,0x0028
+,0x0029
+,0x0028
+,0x0028
+,0x0029
+,0x0028
+,0x0029
+,0x0028
+,0x0029
+,0x0028
+,0x712C
+,0xF1A8
+,0xF9D4
+,0x208E
+,0x4BC2
+,0xF280
+,0xF280
+,0x4BC2
+,0x208E
+,0xF9D4
+,0xF1A8
+,0x712C
+,0x0000
+,0x0200
+,0x0100
+,0x0080
+,0x0040
+,0x0020
+,0x0010
+,0x0008
+,0x0004
+,0x0002
+,0x0001
+,0x02DC
+,0x016E
+,0x00B7
+,0x0287
+,0x039F
+,0x0313
+,0x0355
+,0x0376
+,0x01BB
+,0x0201
+,0x03DC
+,0x01EE
+,0x00F7
+,0x02A7
+,0x038F
+,0x031B
+,0x00FC
+,0x00FC
+,0x0198
+,0x0198
+,0x0168
+,0x0350
+,0x01B4
+,0x01B4
+,0x0089
+,0x002C
+,0x0058
+,0x002C
+,0x0400
+,0x0000
+,0x0003
+,0xFAED
+,0xFED0
+,0x09E2
+,0x166A
+,0x1BEF
+,0x166A
+,0x09E2
+,0xFED0
+,0xFAED
+,0x2715
+,0x58EB
+,0x58EB
+,0x2715
+,0xFF8F
+,0xFF25
+,0xFEA1
+,0xFE12
+,0xFD8A
+,0xFD26
+,0xFD04
+,0xFD43
+,0xFE00
+,0xFF4E
+,0x0139
+,0x03B9
+,0x06BB
+,0x0A1A
+,0x0DA5
+,0x111F
+,0x144B
+,0x16EC
+,0x18CC
+,0x19C7
+,0x19C7
+,0x18CC
+,0x16EC
+,0x144B
+,0x111F
+,0x0DA5
+,0x0A1A
+,0x06BB
+,0x03B9
+,0x0139
+,0xFF4E
+,0xFE00
+,0xFD43
+,0xFD04
+,0xFD26
+,0xFD8A
+,0xFE12
+,0xFEA1
+,0xFF25
+,0xFF8F
+,0x0002
+,0x0004
+,0x47B3
+,0xBAC5
+,0x0B85
+,0x0005
+,0x299A
+,0x0004
+,0x000A
+,0x0660
+,0x0CCD
+,0x0003
+,0x0006
+,0x0080
+,0x002C
+,0x0020
+,0x0027
+,0xFF4F
+,0xFDB1
+,0xFE2E
+,0x0465
+,0x0EF1
+,0x161E
+,0x1382
+,0x0983
+,0x007B
+,0xFD66
+,0xFE7D
+,0xFFE2
+,0x0031
+,0x000D
+,0x4000
+,0xFD24
+,0x513A
+,0xCAEC
+,0x3514
+,0xAEC6
+,0x02DC
+,0x4000
+,0xEFB5
+,0x6EAE
+,0x8DAB
+,0x7255
+,0x9152
+,0x104B
+,0x2518
+,0x1FBB
+,0x14A2
+,0x0D6A
+,0x08B9
+,0x05AC
+,0x03B0
+,0x0266
+,0x018F
+,0x0104
+,0x00A9
+,0x006E
+,0x0047
+,0x0001
+,0x0164
+,0x019A
+,0x0001
+,0x0002
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x7FFF
+,0x0000
+,0x0100
+,0xF500
+,0x1C00
+,0x5A00
+,0x0100
+,0xFF00
+,0xF800
+,0x2000
+,0x4F00
+,0x0100
+,0xFE00
+,0xFC00
+,0x2200
+,0x4700
+,0x0000
+,0xFD00
+,0x0100
+,0x2300
+,0x3D00
+,0xFF00
+,0xFE00
+,0x0500
+,0x2200
+,0x3600
+,0xFF00
+,0xFF00
+,0x0900
+,0x2100
+,0x2F00
+,0x0000
+,0x0100
+,0x0C00
+,0x1F00
+,0x2900
+,0x0000
+,0x0300
+,0x0E00
+,0x1D00
+,0x2500
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x7FFF
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0004
+,0x0008
+,0x0308
+,0x0312
+,0x01CC
+,0x017C
+,0x0019
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0xE000
+,0x1840
+,0xC880
+,0xFFEE
+,0x0000
+,0x4000
+,0x2680
+,0xFF81
+,0xE000
+,0x5000
+,0xD080
+,0xFFB3
+,0xF800
+,0x4500
+,0xD380
+,0xFFE2
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0F80
+,0xDB80
+,0x21C0
+,0xFFCC
+,0x0000
+,0xC680
+,0x0540
+,0x0023
+,0x33C0
+,0xDAC0
+,0x5900
+,0xFFDA
+,0x0AC0
+,0xDF80
+,0x1940
+,0xFFF7
+,0x7FFF
+,0x50C3
+,0x47FA
+,0x4026
+,0x392C
+,0x32F5
+,0x2D6A
+,0x287A
+,0x2413
+,0x2027
+,0x1CA8
+,0x198A
+,0x16C3
+,0x1449
+,0x1214
+,0x101D
+,0x0E5D
+,0x0CCD
+,0x0B68
+,0x0A2B
+,0x0910
+,0x0813
+,0x0015
+,0x0002
+,0x0080
+,0x2848
+,0x051F
+,0x0001
+,0x0010
+,0xFC40
+,0xFC40
+,0xFD94
+,0xFD80
+,0xFE80
+,0xFE80
+,0xFE7C
+,0xFE7F
+,0x02F4
+,0x0001
+,0x0080
+,0x0080
+,0x1000
+,0x0080
+,0x1000
+,0x1000
+,0x0400
+,0x599A
+,0x199A
+,0x0666
+,0x0021
+,0x2000
+,0x2000
+,0x2000
+,0xFFE4
+,0x0032
+,0x000A
+,0x2000
+,0x4000
+,0x0800
+,0x0400
+,0x000C
+,0x0005
+,0x000C
+,0x00FF
+,0x083D
+,0x4000
+,0x062F
+,0x404C
+,0x01B9
+,0x4052
+,0x0155
+,0x405B
+,0x0704
+,0x4069
+,0x0786
+,0x4071
+,0x0E9A
+,0x4077
+,0x0FEB
+,0x4080
+,0x0000
+,0x0000
+,0xFFD5
+,0x0001
+,0x0375
+,0x001E
+,0x0AAB
+,0x2000
+,0x2AAB
+,0x0040
+,0x0005
+,0x001E
+,0x4093
+,0xFEE0
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+};
+
+const unsigned short bin_coeff_E2[] = { 
+0x0000
+,0x01FF
+,0x0400
+,0x0006
+,0x2AAB
+,0x0324
+,0x0324
+,0x0324
+,0x010C
+,0x010C
+,0x010C
+,0x1111
+,0x1259
+,0x0001
+,0x005A
+,0x0E9B
+,0x0FFF
+,0x0FFF
+,0x0020
+,0x0001
+,0x0001
+,0x0CCD
+,0xFFE0
+,0xFFD8
+,0x00FF
+,0xFFAC
+,0xFFBC
+,0xFF00
+,0x0020
+,0x0048
+,0x0050
+,0x0050
+,0x000E
+,0x0002
+,0x7000
+,0x0800
+,0xFFF8
+,0x0008
+,0x002B
+,0xFFF6
+,0xFFF8
+,0xFFFE
+,0x0003
+,0x0008
+,0x000D
+,0x000F
+,0x0014
+,0x0019
+,0x0000
+,0x0800
+,0x6580
+,0x0000
+,0x0000
+,0x7FFF
+,0x0008
+,0x0078
+,0xFEF5
+,0xFEE8
+,0x0003
+,0x0080
+,0x0080
+,0x0080
+,0x0300
+,0x0006
+,0xC080
+,0xF000
+,0x0660
+,0xDA80
+,0x0000
+,0x0001
+,0x0001
+,0xFFE4
+,0xFFE8
+,0x0080
+,0x0034
+,0x0001
+,0xFFFF
+,0x0001
+,0xFFFE
+,0x3AC0
+,0x3340
+,0x2BC0
+,0x07C0
+,0x05C0
+,0x03E0
+,0x0008
+,0x1000
+,0x2000
+,0xFF01
+,0xFFE5
+,0xFFE9
+,0x0DA8
+,0x000E
+,0xF75E
+,0x1136
+,0xEC7B
+,0x0D3C
+,0xFA9A
+,0xFC47
+,0xF58B
+,0x1055
+,0x3DDA
+,0x3DDA
+,0x1055
+,0xF58B
+,0xFC47
+,0x1B17
+,0x362A
+,0x1B17
+,0x67DA
+,0xA798
+,0xFDA6
+,0xF8BE
+,0xF36E
+,0xF0D4
+,0xF368
+,0xFB18
+,0x04E8
+,0x0C98
+,0x0F2C
+,0x0C92
+,0x0742
+,0x025A
+,0x0028
+,0x0029
+,0x0028
+,0x0029
+,0x0028
+,0x0029
+,0x0028
+,0x0028
+,0x0029
+,0x0028
+,0x0029
+,0x0028
+,0x0028
+,0x0029
+,0x0028
+,0x0029
+,0x0028
+,0x0029
+,0x0028
+,0x712C
+,0xF1A8
+,0xF9D4
+,0x208E
+,0x4BC2
+,0xF280
+,0xF280
+,0x4BC2
+,0x208E
+,0xF9D4
+,0xF1A8
+,0x712C
+,0x0000
+,0x0200
+,0x0100
+,0x0080
+,0x0040
+,0x0020
+,0x0010
+,0x0008
+,0x0004
+,0x0002
+,0x0001
+,0x02DC
+,0x016E
+,0x00B7
+,0x0287
+,0x039F
+,0x0313
+,0x0355
+,0x0376
+,0x01BB
+,0x0201
+,0x03DC
+,0x01EE
+,0x00F7
+,0x02A7
+,0x038F
+,0x031B
+,0x00FC
+,0x00FC
+,0x0198
+,0x0198
+,0x0168
+,0x0350
+,0x01B4
+,0x01B4
+,0x0089
+,0x002C
+,0x0058
+,0x002C
+,0x0400
+,0x0000
+,0x0003
+,0xFAED
+,0xFED0
+,0x09E2
+,0x166A
+,0x1BEF
+,0x166A
+,0x09E2
+,0xFED0
+,0xFAED
+,0x2715
+,0x58EB
+,0x58EB
+,0x2715
+,0xFF8F
+,0xFF25
+,0xFEA1
+,0xFE12
+,0xFD8A
+,0xFD26
+,0xFD04
+,0xFD43
+,0xFE00
+,0xFF4E
+,0x0139
+,0x03B9
+,0x06BB
+,0x0A1A
+,0x0DA5
+,0x111F
+,0x144B
+,0x16EC
+,0x18CC
+,0x19C7
+,0x19C7
+,0x18CC
+,0x16EC
+,0x144B
+,0x111F
+,0x0DA5
+,0x0A1A
+,0x06BB
+,0x03B9
+,0x0139
+,0xFF4E
+,0xFE00
+,0xFD43
+,0xFD04
+,0xFD26
+,0xFD8A
+,0xFE12
+,0xFEA1
+,0xFF25
+,0xFF8F
+,0x0002
+,0x0004
+,0x47B3
+,0xBAC5
+,0x0B85
+,0x0005
+,0x299A
+,0x0004
+,0x000A
+,0x0660
+,0x0CCD
+,0x0003
+,0x0006
+,0x0080
+,0x002C
+,0x0020
+,0x0027
+,0xFF4F
+,0xFDB1
+,0xFE2E
+,0x0465
+,0x0EF1
+,0x161E
+,0x1382
+,0x0983
+,0x007B
+,0xFD66
+,0xFE7D
+,0xFFE2
+,0x0031
+,0x000D
+,0x4000
+,0xFD24
+,0x513A
+,0xCAEC
+,0x3514
+,0xAEC6
+,0x02DC
+,0x4000
+,0xEFB5
+,0x6EAE
+,0x8DAB
+,0x7255
+,0x9152
+,0x104B
+,0x2518
+,0x1FBB
+,0x14A2
+,0x0D6A
+,0x08B9
+,0x05AC
+,0x03B0
+,0x0266
+,0x018F
+,0x0104
+,0x00A9
+,0x006E
+,0x0047
+,0x0001
+,0x0164
+,0x019A
+,0x0001
+,0x0002
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x7FFF
+,0x0000
+,0x0100
+,0xF500
+,0x1C00
+,0x5A00
+,0x0100
+,0xFF00
+,0xF800
+,0x2000
+,0x4F00
+,0x0100
+,0xFE00
+,0xFC00
+,0x2200
+,0x4700
+,0x0000
+,0xFD00
+,0x0100
+,0x2300
+,0x3D00
+,0xFF00
+,0xFE00
+,0x0500
+,0x2200
+,0x3600
+,0xFF00
+,0xFF00
+,0x0900
+,0x2100
+,0x2F00
+,0x0000
+,0x0100
+,0x0C00
+,0x1F00
+,0x2900
+,0x0000
+,0x0300
+,0x0E00
+,0x1D00
+,0x2500
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x7FFF
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0004
+,0x0008
+,0x0308
+,0x0312
+,0x01CC
+,0x017C
+,0x0019
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0xE000
+,0x1840
+,0xC880
+,0xFFEE
+,0x0000
+,0x4000
+,0x2680
+,0xFF81
+,0xE000
+,0x5000
+,0xD080
+,0xFFB3
+,0xF800
+,0x4500
+,0xD380
+,0xFFE2
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0F80
+,0xDB80
+,0x21C0
+,0xFFCC
+,0x0000
+,0xC680
+,0x0540
+,0x0023
+,0x33C0
+,0xDAC0
+,0x5900
+,0xFFDA
+,0x0AC0
+,0xDF80
+,0x1940
+,0xFFF7
+,0x7FFF
+,0x50C3
+,0x47FA
+,0x4026
+,0x392C
+,0x32F5
+,0x2D6A
+,0x287A
+,0x2413
+,0x2027
+,0x1CA8
+,0x198A
+,0x16C3
+,0x1449
+,0x1214
+,0x101D
+,0x0E5D
+,0x0CCD
+,0x0B68
+,0x0A2B
+,0x0910
+,0x0813
+,0x0015
+,0x0002
+,0x0080
+,0x2848
+,0x051F
+,0x0001
+,0x0010
+,0xFC40
+,0xFC40
+,0xFD94
+,0xFD80
+,0xFE80
+,0xFE80
+,0xFE7C
+,0xFE7F
+,0x02F4
+,0x0001
+,0x0080
+,0x0080
+,0x1000
+,0x0080
+,0x1000
+,0x1000
+,0x0400
+,0x599A
+,0x199A
+,0x0666
+,0x0021
+,0x2000
+,0x2000
+,0x2000
+,0xFFE4
+,0x0032
+,0x000A
+,0x2000
+,0x4000
+,0x0800
+,0x0400
+,0x000C
+,0x0005
+,0x000C
+,0x0038
+,0x01A7
+,0x4000
+,0x0143
+,0x4009
+,0x0000
+,0x0000
+,0x0929
+,0x4020
+,0x0721
+,0x4041
+,0x0755
+,0x4052
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0x0000
+,0xFFD5
+,0x0001
+,0x0375
+,0x001E
+,0x0AAB
+,0x2000
+,0x2AAB
+,0x0040
+,0x0005
+,0x001E
+,0x0001
+,0xFEE0
+,0xFED8
+,0xFED8
+,0x0000
+,0x0040
+,0x40A2
+,0x0000
+};
+
+const unsigned short bin_hw_coeff[] = {
+0x0000
+,0x0027
+,0xfffd
+,0xfffc
+,0x0002
+,0x000a
+,0x0005
+,0xfff4
+,0xffed
+,0x0004
+,0x0024
+,0x0018
+,0xffd8
+,0xffb1
+,0x0006
+,0x00cd
+,0x0179
+,0x0001
+,0xfffd
+,0x0004
+,0x0000   
+,0x000b
+,0xffe0
+,0x0047
+,0xff75
+,0x0134
+,0x04c4
+,0xff9c
+,0x000f
+,0x0007
+,0xfff7
+,0x0006
+,0x0001
+,0x0008
+,0xffdf
+,0x005d
+,0xff18
+,0x034a
+,0xff81
+,0x03d9
+,0x00a6
+,0xfffe
+,0x0012
+,0xffa6
+,0x0000
+};
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6628/inc/mt6628_fm.h b/drivers/mtk_wcn_combo/drv_fm/mt6628/inc/mt6628_fm.h
new file mode 100755 (executable)
index 0000000..43ba9d6
--- /dev/null
@@ -0,0 +1,59 @@
+/* mt6628_fm.h
+ *
+ * (C) Copyright 2009 
+ * MediaTek <www.MediaTek.com>
+ * Hongcheng <hongcheng.xia@MediaTek.com>
+ *
+ * MT6628 FM Radio Driver --  head file
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __MT6628_FM_H__
+#define __MT6628_FM_H__
+
+#include "fm_typedef.h"
+
+//#define FM_PowerOn_with_ShortAntenna
+#define MT6628_RSSI_TH_LONG    0xFF01      //FM radio long antenna RSSI threshold(11.375dBuV)
+#define MT6628_RSSI_TH_SHORT   0xFEE0      //FM radio short antenna RSSI threshold(-1dBuV)
+#define MT6628_CQI_TH          0x00E9      //FM radio Channel quality indicator threshold(0x0000~0x00FF)
+#define MT6628_SEEK_SPACE      1           //FM radio seek space,1:100KHZ; 2:200KHZ
+#define MT6628_SCAN_CH_SIZE    40          //FM radio scan max channel size
+#define MT6628_BAND            1           //FM radio band, 1:87.5MHz~108.0MHz; 2:76.0MHz~90.0MHz; 3:76.0MHz~108.0MHz; 4:special
+#define MT6628_BAND_FREQ_L     875         //FM radio special band low freq(Default 87.5MHz)
+#define MT6628_BAND_FREQ_H     1080        //FM radio special band high freq(Default 108.0MHz)
+#define MT6628_DEEMPHASIS_50us TRUE
+
+#define MT6628_SLAVE_ADDR    0xE0      //0x70 7-bit address
+#define MT6628_MAX_COUNT     100
+
+#ifdef MTK_FM_50KHZ_SUPPORT
+#define MT6628_SCANTBL_SIZE  26 //16*uinit16_t
+#else
+#define MT6628_SCANTBL_SIZE  16                //16*uinit16_t
+#endif
+
+#define AFC_ON  0x01
+#if AFC_ON
+#define FM_MAIN_CTRL_INIT  0x480
+#else
+#define FM_MAIN_CTRL_INIT  0x080
+#endif
+
+#define ext_clk                                //if define ext_clk use external reference clock or mask will use internal
+#define MT6628_DEV                     "MT6628"   
+
+#endif //end of #ifndef __MT6628_FM_H__
+
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6628/inc/mt6628_fm_cmd.h b/drivers/mtk_wcn_combo/drv_fm/mt6628/inc/mt6628_fm_cmd.h
new file mode 100755 (executable)
index 0000000..96b42b3
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef __MT6628_FM_CMD_H__
+#define __MT6628_FM_CMD_H__
+
+#include <linux/types.h>
+#include "fm_typedef.h"
+
+/* FM basic-operation's opcode */
+#define FM_BOP_BASE (0x80)
+enum {
+    FM_WRITE_BASIC_OP       = (FM_BOP_BASE + 0x00),
+    FM_UDELAY_BASIC_OP      = (FM_BOP_BASE + 0x01),
+    FM_RD_UNTIL_BASIC_OP    = (FM_BOP_BASE + 0x02),
+    FM_MODIFY_BASIC_OP      = (FM_BOP_BASE + 0x03),
+    FM_MSLEEP_BASIC_OP      = (FM_BOP_BASE + 0x04),
+    FM_MAX_BASIC_OP         = (FM_BOP_BASE + 0x05)
+};
+
+/* FM BOP's size */
+#define FM_WRITE_BASIC_OP_SIZE      (3)
+#define FM_UDELAY_BASIC_OP_SIZE     (4)
+#define FM_RD_UNTIL_BASIC_OP_SIZE   (5)
+#define FM_MODIFY_BASIC_OP_SIZE     (5)
+#define FM_MSLEEP_BASIC_OP_SIZE     (4)
+
+fm_s32 mt6628_pwrup_fpga_on(fm_u8 *buf, fm_s32 buf_size);
+fm_s32 mt6628_pwrup_clock_on(fm_u8 *buf, fm_s32 buf_size);
+fm_s32 mt6628_pwrup_digital_init(fm_u8 *buf, fm_s32 buf_size);
+fm_s32 mt6628_pwrdown(fm_u8 *buf, fm_s32 buf_size);
+fm_s32 mt6628_rampdown(fm_u8 *buf, fm_s32 buf_size);
+fm_s32 mt6628_tune(fm_u8 *buf, fm_s32 buf_size, fm_u16 freq, fm_u16 chan_para);
+fm_s32 mt6628_seek(fm_u8 *buf, fm_s32 buf_size, fm_u16 seekdir, fm_u16 space, fm_u16 max_freq, fm_u16 min_freq);
+fm_s32 mt6628_scan(fm_u8 *buf, fm_s32 buf_size, fm_u16 scandir, fm_u16 space, fm_u16 max_freq, fm_u16 min_freq);
+fm_s32 mt6628_cqi_get(fm_u8 *buf, fm_s32 buf_size);
+fm_s32 mt6628_get_reg(fm_u8 *buf, fm_s32 buf_size, fm_u8 addr);
+fm_s32 mt6628_set_reg(fm_u8 *buf, fm_s32 buf_size, fm_u8 addr, fm_u16 value);
+fm_s32 mt6628_patch_download(fm_u8 *buf, fm_s32 buf_size, fm_u8 seg_num, fm_u8 seg_id, const fm_u8 *src, fm_s32 seg_len);
+fm_s32 mt6628_coeff_download(fm_u8 *buf, fm_s32 buf_size, fm_u8 seg_num, fm_u8 seg_id, const fm_u8 *src, fm_s32 seg_len);
+fm_s32 mt6628_hwcoeff_download(fm_u8 *buf, fm_s32 buf_size, fm_u8 seg_num, fm_u8 seg_id, const fm_u8 *src, fm_s32 seg_len);
+fm_s32 mt6628_rom_download(fm_u8 *buf, fm_s32 buf_size, fm_u8 seg_num, fm_u8 seg_id, const fm_u8 *src, fm_s32 seg_len);
+fm_s32 mt6628_full_cqi_req(fm_u8 *buf, fm_s32 buf_size, fm_u16 *freq, fm_s32 cnt, fm_s32 type);
+
+/*
+ * fm_get_channel_space - get the spcace of gived channel
+ * @freq - value in 760~1080 or 7600~10800
+ *
+ * Return 0, if 760~1080; return 1, if 7600 ~ 10800, else err code < 0
+ */
+extern fm_s32 fm_get_channel_space(int freq);
+
+#endif
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6628/inc/mt6628_fm_lib.h b/drivers/mtk_wcn_combo/drv_fm/mt6628/inc/mt6628_fm_lib.h
new file mode 100755 (executable)
index 0000000..d4f571d
--- /dev/null
@@ -0,0 +1,98 @@
+#ifndef __MT6628_FM_LIB_H__
+#define __MT6628_FM_LIB_H__
+
+#include "fm_typedef.h"
+
+enum {
+    DSPPATCH = 0xFFF9,
+    USDELAY = 0xFFFA,
+    MSDELAY = 0xFFFB,
+    HW_VER = 0xFFFD,
+    POLL_N = 0xFFFE, //poling check if bit(n) is '0'
+    POLL_P = 0xFFFF, //polling check if bit(n) is '1'
+};
+
+enum {
+    FM_PUS_DSPPATCH = DSPPATCH,
+    FM_PUS_USDELAY = USDELAY,
+    FM_PUS_MSDELAY = MSDELAY,
+    FM_PUS_HW_VER = HW_VER,
+    FM_PUS_POLL_N = POLL_N, //poling check if bit(n) is '0'
+    FM_PUS_POLL_P = POLL_P, //polling check if bit(n) is '1'
+    FM_PUS_MAX
+};
+
+enum {
+    DSP_PATH = 0x02,
+    DSP_COEFF = 0x03,
+    DSP_HW_COEFF = 0x04
+};
+
+enum IMG_TYPE {
+    IMG_WRONG = 0,
+    IMG_ROM,
+    IMG_PATCH,
+    IMG_COEFFICIENT,
+    IMG_HW_COEFFICIENT
+};
+
+enum {
+    mt6628_E1 = 0,
+    mt6628_E2
+};
+
+enum {
+    FM_LONG_ANA = 0,
+    FM_SHORT_ANA
+};
+
+enum {
+    MT6628_I2S_ON = 0,
+    MT6628_I2S_OFF
+};
+
+enum {
+    MT6628_I2S_MASTER = 0,
+    MT6628_I2S_SLAVE
+};
+
+enum {
+    MT6628_I2S_32K = 0,
+    MT6628_I2S_44K,
+    MT6628_I2S_48K
+};
+/*
+struct mt6628_fm_i2s_info {
+    fm_s32 status;
+    fm_s32 mode;
+    fm_s32 rate;
+};
+*/
+struct mt6628_fm_cqi {
+    fm_u16 ch;
+    fm_u16 rssi;
+    fm_u16 reserve;
+};
+
+struct adapt_fm_cqi {
+    fm_s32 ch;
+    fm_s32 rssi;
+    fm_s32 reserve;
+};
+
+struct mt6628_full_cqi {
+    fm_u16 ch;
+    fm_u16 rssi;
+    fm_u16 pamd;
+    fm_u16 pr;
+    fm_u16 fpamd;
+    fm_u16 mr;
+    fm_u16 atdc;
+    fm_u16 prx;
+    fm_u16 atdev;
+    fm_u16 smg; // soft-mute gain
+    fm_u16 drssi; // delta rssi
+};
+
+
+#endif
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6628/inc/mt6628_fm_link.h b/drivers/mtk_wcn_combo/drv_fm/mt6628/inc/mt6628_fm_link.h
new file mode 100755 (executable)
index 0000000..c7337fc
--- /dev/null
@@ -0,0 +1,68 @@
+/* mt6626_fm_ctrl_link.h
+ *
+ * (C) Copyright 2009
+ * MediaTek <www.MediaTek.com>
+ * Hongcheng <hongcheng.xia@MediaTek.com>
+ *
+ * MT6626 FM Radio Driver -- setup data link
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#if 0
+#ifndef __MT6628_FM_LINK_H__
+#define __MT6628_FM_LINK_H__
+
+#include <linux/wait.h>
+#include "fm_link.h"
+#include "fm_utils.h"
+
+#define RX_BUF_SIZE 128
+#define TX_BUF_SIZE 1024
+
+#define SW_RETRY_CNT            (1)
+#define SW_RETRY_CNT_MAX        (5)
+#define SW_WAIT_TIMEOUT_MAX     (100)
+
+// FM operation timeout define for error handle
+#define TEST_TIMEOUT            (3)
+#define FSPI_EN_TIMEOUT         (3)
+#define FSPI_MUXSEL_TIMEOUT     (3)
+#define FSPI_RD_TIMEOUT         (3)
+#define FSPI_WR_TIMEOUT         (3)
+#define I2C_RD_TIMEOUT          (3)
+#define I2C_WR_TIMEOUT          (3)
+#define EN_TIMEOUT              (3)
+#define RST_TIMEOUT             (3)
+#define TUNE_TIMEOUT            (3)
+#define SM_TUNE_TIMEOUT         (6)
+#define SEEK_TIMEOUT            (15)
+#define SCAN_TIMEOUT            (15) //usualy scan will cost 10 seconds 
+#define RDS_RX_EN_TIMEOUT       (3)
+#define RDS_DATA_TIMEOUT        (100)
+#define RAMPDOWN_TIMEOUT        (3)
+#define MCUCLK_TIMEOUT          (3)
+#define MODEMCLK_TIMEOUT        (3)
+#define RDS_TX_TIMEOUT          (3)
+#define PATCH_TIMEOUT           (3)
+#define COEFF_TIMEOUT           (3)
+#define HWCOEFF_TIMEOUT         (3)
+#define ROM_TIMEOUT             (3)
+
+struct fm_link_event {
+    struct fm_flag_event *ln_event;
+    struct fm_res_ctx result; // seek/scan/read/RDS
+};
+#endif
+#endif
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6628/inc/mt6628_fm_reg.h b/drivers/mtk_wcn_combo/drv_fm/mt6628/inc/mt6628_fm_reg.h
new file mode 100755 (executable)
index 0000000..d4ab3c8
--- /dev/null
@@ -0,0 +1,90 @@
+#ifndef __MT6628_FM_REG_H__
+#define __MT6628_FM_REG_H__
+
+enum MT6628_REG{ 
+       FM_MAIN_CG1_CTRL = 0x60,
+       FM_MAIN_CG2_CTRL = 0x61,
+    FM_MAIN_HWVER = 0x62,
+    FM_MAIN_CTRL = 0x63,
+    FM_CHANNEL_SET = 0x65,
+    FM_MAIN_CFG1 = 0x66,
+    FM_MAIN_CFG2 = 0x67,
+    FM_MAIN_MCLKDESENSE = 0x38,
+    FM_MAIN_INTR = 0x69,
+    FM_MAIN_INTRMASK = 0x6A,
+    FM_MAIN_EXTINTRMASK = 0x6B,
+    FM_RSSI_IND = 0x6C,
+    FM_RSSI_TH = 0x6D,
+    FM_MAIN_RESET = 0x6E,
+    FM_MAIN_CHANDETSTAT = 0x6F,  
+    FM_RDS_CFG0 = 0x80,
+    FM_RDS_INFO = 0x81,
+    FM_RDS_DATA_REG = 0x82,
+    FM_RDS_GOODBK_CNT = 0x83,
+    FM_RDS_BADBK_CNT = 0x84,
+    FM_RDS_PWDI = 0x85,
+    FM_RDS_PWDQ = 0x86,
+    FM_RDS_FIFO_STATUS0 = 0x87,
+    FM_FT_CON9 = 0x8F,
+       FM_DSP_PATCH_CTRL = 0x90,
+       FM_DSP_PATCH_OFFSET = 0x91,
+       FM_DSP_PATCH_DATA = 0x92,
+       FM_DSP_MEM_CTRL4 = 0x93,
+       FM_ADDR_PAMD = 0xB4,
+       FM_RDS_BDGRP_ABD_CTRL_REG = 0xB6,
+       FM_RDS_POINTER = 0xF0,   
+};
+
+//RDS_BDGRP_ABD_CTRL_REG
+enum{
+       BDGRP_ABD_EN = 0x0001,
+       BER_RUN = 0x2000
+};
+#define FM_DAC_CON1 0x83
+#define FM_DAC_CON2 0x84
+#define FM_FT_CON0 0x86
+enum{
+       FT_EN = 0x0001
+};
+          
+#define FM_I2S_CON0 0x90
+enum{
+       I2S_EN = 0x0001,
+       FORMAT = 0x0002,
+       WLEN = 0x0004,
+       I2S_SRC = 0x0008
+};
+
+//FM_MAIN_CTRL
+enum{
+       TUNE = 0x0001,
+       SEEK = 0x0002,
+       SCAN = 0x0004,
+       CQI_READ = 0x0008,
+       RDS_MASK = 0x0010,
+       MUTE = 0x0020,
+       RDS_BRST = 0x0040,
+       RAMP_DOWN = 0x0100,
+};
+
+//FM_MAIN_INTR
+enum{
+       FM_INTR_STC_DONE = 0x0001,
+       FM_INTR_IQCAL_DONE = 0x0002,                            
+       FM_INTR_DESENSE_HIT     = 0x0004,                               
+       FM_INTR_CHNL_CHG = 0x0008,                              
+       FM_INTR_SW_INTR = 0x0010,       
+       FM_INTR_RDS = 0x0020
+};
+
+enum{
+    ANTENNA_TYPE = 0x0010,  //0x61 D4, 0:long,  1:short
+    ANALOG_I2S = 0x0080,      //0x61 D7, 0:lineout,  1:I2S 
+    DE_EMPHASIS = 0x1000,    //0x61 D12,0:50us,  1:75 us
+};
+
+#define OSC_FREQ_BITS 0x0070 //0x60 bit4~6
+#define OSC_FREQ_MASK (~OSC_FREQ_BITS)
+
+#endif //__MT6628_FM_REG_H__
+
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6628/pub/mt6628_fm_cmd.c b/drivers/mtk_wcn_combo/drv_fm/mt6628/pub/mt6628_fm_cmd.c
new file mode 100755 (executable)
index 0000000..799ed11
--- /dev/null
@@ -0,0 +1,915 @@
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include "fm_typedef.h"
+#include "fm_dbg.h"
+#include "fm_err.h"
+#include "fm_rds.h"
+#include "fm_config.h"
+#include "fm_link.h"
+
+#include "mt6628_fm_reg.h"
+//#include "mt6628_fm_link.h"
+#include "mt6628_fm.h"
+#include "mt6628_fm_cmd.h"
+#include "mt6628_fm_cust_cfg.h"
+
+extern fm_cust_cfg mt6628_fm_config;
+
+static fm_s32 fm_bop_write(fm_u8 addr, fm_u16 value, fm_u8 *buf, fm_s32 size)
+{
+    if (size < (FM_WRITE_BASIC_OP_SIZE + 2)) {
+        return (-1);
+    }
+
+    if (buf == NULL) {
+        return (-2);
+    }
+
+    buf[0] = FM_WRITE_BASIC_OP;
+    buf[1] = FM_WRITE_BASIC_OP_SIZE;
+    buf[2] = addr;
+    buf[3] = (fm_u8)((value) & 0x00FF);
+    buf[4] = (fm_u8)((value >> 8) & 0x00FF);
+
+    WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4]);
+
+    return (FM_WRITE_BASIC_OP_SIZE + 2);
+}
+
+
+static fm_s32 fm_bop_udelay(fm_u32 value, fm_u8 *buf, fm_s32 size)
+{
+    if (size < (FM_UDELAY_BASIC_OP_SIZE + 2)) {
+        return (-1);
+    }
+
+    if (buf == NULL) {
+        return (-2);
+    }
+
+    buf[0] = FM_UDELAY_BASIC_OP;
+    buf[1] = FM_UDELAY_BASIC_OP_SIZE;
+    buf[2] = (fm_u8)((value) & 0x000000FF);
+    buf[3] = (fm_u8)((value >> 8) & 0x000000FF);
+    buf[4] = (fm_u8)((value >> 16) & 0x000000FF);
+    buf[5] = (fm_u8)((value >> 24) & 0x000000FF);
+
+    WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
+
+    return (FM_UDELAY_BASIC_OP_SIZE + 2);
+}
+
+
+static fm_s32 fm_bop_rd_until(fm_u8 addr, fm_u16 mask, fm_u16 value, fm_u8 *buf, fm_s32 size)
+{
+    if (size < (FM_RD_UNTIL_BASIC_OP_SIZE + 2)) {
+        return (-1);
+    }
+
+    if (buf == NULL) {
+        return (-2);
+    }
+
+    buf[0] = FM_RD_UNTIL_BASIC_OP;
+    buf[1] = FM_RD_UNTIL_BASIC_OP_SIZE;
+    buf[2] = addr;
+    buf[3] = (fm_u8)((mask) & 0x00FF);
+    buf[4] = (fm_u8)((mask >> 8) & 0x00FF);
+    buf[5] = (fm_u8)((value) & 0x00FF);
+    buf[6] = (fm_u8)((value >> 8) & 0x00FF);
+
+    WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
+
+    return (FM_RD_UNTIL_BASIC_OP_SIZE + 2);
+}
+
+
+static fm_s32 fm_bop_modify(fm_u8 addr, fm_u16 mask_and, fm_u16 mask_or, fm_u8 *buf, fm_s32 size)
+{
+    if (size < (FM_MODIFY_BASIC_OP_SIZE + 2)) {
+        return (-1);
+    }
+
+    if (buf == NULL) {
+        return (-2);
+    }
+
+    buf[0] = FM_MODIFY_BASIC_OP;
+    buf[1] = FM_MODIFY_BASIC_OP_SIZE;
+    buf[2] = addr;
+    buf[3] = (fm_u8)((mask_and) & 0x00FF);
+    buf[4] = (fm_u8)((mask_and >> 8) & 0x00FF);
+    buf[5] = (fm_u8)((mask_or) & 0x00FF);
+    buf[6] = (fm_u8)((mask_or >> 8) & 0x00FF);
+
+    WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
+
+    return (FM_MODIFY_BASIC_OP_SIZE + 2);
+}
+
+#if 0
+static fm_s32 fm_bop_msleep(fm_u32 value, fm_u8 *buf, fm_s32 size)
+{
+    if (size < (FM_MSLEEP_BASIC_OP_SIZE + 2)) {
+        return (-1);
+    }
+
+    if (buf == NULL) {
+        return (-2);
+    }
+
+    buf[0] = FM_MSLEEP_BASIC_OP;
+    buf[1] = FM_MSLEEP_BASIC_OP_SIZE;
+    buf[2] = (fm_u8)((value) & 0x000000FF);
+    buf[3] = (fm_u8)((value >> 8) & 0x000000FF);
+    buf[4] = (fm_u8)((value >> 16) & 0x000000FF);
+    buf[5] = (fm_u8)((value >> 24) & 0x000000FF);
+
+    WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
+
+    return (FM_MSLEEP_BASIC_OP_SIZE + 2);
+}
+#endif
+
+/*
+inline fm_s32 fm_get_channel_space(fm_s32 freq)
+{
+    if ((freq >= 760) && (freq <= 1080)) {
+        return 0;
+    } else if ((freq >= 7600) && (freq <= 10800)) {
+        return 1;
+    } else {
+        return -1;
+    }
+}
+*/
+
+fm_s32 mt6628_pwrup_fpga_on(fm_u8 *buf, fm_s32 buf_size)
+{
+    fm_s32 pkt_size = 0;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_ENABLE_OPCODE;
+    pkt_size = 4;
+
+    //Turn on Central Bias + FC
+    pkt_size += fm_bop_write(0x01, 0x4A00, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_udelay(30000, &buf[pkt_size], buf_size - pkt_size);//delay 30ms
+    pkt_size += fm_bop_write(0x01, 0x6A00, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_udelay(50000, &buf[pkt_size], buf_size - pkt_size);//delay 50ms
+    pkt_size += fm_bop_write(0x02, 0x099C, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x01, 0x6B82, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x04, 0x0142, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x05, 0x00E7, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x0A, 0x0060, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x0C, 0xAF8F, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x0D, 0x0888, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x10, 0x0E8D, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x27, 0x0104, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x0e, 0x0040, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x03, 0x9860, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x3F, 0xAD16, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x3E, 0x3280, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x06, 0x0125, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x08, 0x15B8, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x28, 0x0000, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x00, 0x0167, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x3A, 0x0004, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x25, 0x0403, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x20, 0x2720, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x22, 0x9980, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x25, 0x0803, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x1E, 0x0863, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_udelay(50000, &buf[pkt_size], buf_size - pkt_size);//delay 50ms
+    pkt_size += fm_bop_write(0x1E, 0x0865, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_udelay(50000, &buf[pkt_size], buf_size - pkt_size);//delay 50ms
+    pkt_size += fm_bop_write(0x1E, 0x0871, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x2A, 0x1020, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_udelay(100000, &buf[pkt_size], buf_size - pkt_size);//delay 100ms
+    pkt_size += fm_bop_write(0x00, 0x01E7, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_udelay(1000, &buf[pkt_size], buf_size - pkt_size);//delay 1ms
+    pkt_size += fm_bop_write(0x1B, 0x0094, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x1B, 0x0095, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_udelay(200000, &buf[pkt_size], buf_size - pkt_size);//delay 100ms
+    pkt_size += fm_bop_write(0x1B, 0x0094, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x00, 0x0167, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x01, 0x6B8A, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_udelay(1000, &buf[pkt_size], buf_size - pkt_size);//delay 1ms
+    pkt_size += fm_bop_write(0x00, 0xC167, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x0C, 0xAF8F, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_udelay(30000, &buf[pkt_size], buf_size - pkt_size);//delay 1ms
+    pkt_size += fm_bop_write(0x00, 0xF167, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x37, 0x2590, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x09, 0x2964, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x2E, 0x0008, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x11, 0x37D4, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x2B, 0x0032, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x2C, 0x0019, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x71, 0x607F, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x72, 0x878F, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x73, 0x07C3, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x28, 0x0000, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x64, 0x0001, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x6D, 0x1AB2, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x9C, 0x0040, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x9F, 0x0000, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0xB4, 0x8810, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0xB8, 0x006A, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0xBB, 0x006B, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0xCB, 0x00B3, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0xE0, 0xA301, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0xE4, 0x008F, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x9E, 0x2B24, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0xCC, 0x0886, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0xDC, 0x036A, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0xDD, 0x836A, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x0F, 0x1AA8, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x9F, 0x0000, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_udelay(100000, &buf[pkt_size], buf_size - pkt_size);//delay 100ms
+    pkt_size += fm_bop_write(0x63, 0x0480, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_udelay(100000, &buf[pkt_size], buf_size - pkt_size);//delay 100ms
+    pkt_size += fm_bop_write(0x63, 0x0481, &buf[pkt_size], buf_size - pkt_size);
+
+    pkt_size += fm_bop_write(0x6C, 0x0020, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x45, 0x1FFF, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x25, 0x040F, &buf[pkt_size], buf_size - pkt_size);
+
+    pkt_size += fm_bop_write(0x28, 0x7E57, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x11, 0x37DC, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x07, 0x1140, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x27, 0x005C, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x42, 0x0016, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x44, 0x006F, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x46, 0x1DEF, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x47, 0x0210, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x55, 0x0001, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x54, 0x8001, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0xA0, 0xD0B2, &buf[pkt_size], buf_size - pkt_size);
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+
+/*
+ * mt6628_pwrup_clock_on - Wholechip FM Power Up: step 1, FM Digital Clock enable
+ * @buf - target buf
+ * @buf_size - buffer size
+ * return package size
+ */
+fm_s32 mt6628_pwrup_clock_on(fm_u8 *buf, fm_s32 buf_size)
+{
+    fm_s32 pkt_size = 0;
+    fm_u16 de_emphasis;
+    fm_u16 osc_freq;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    de_emphasis = mt6628_fm_config.rx_cfg.deemphasis;//MT6628fm_cust_config_fetch(FM_CFG_RX_DEEMPHASIS);
+    de_emphasis &= 0x0001; //rang 0~1
+    osc_freq = mt6628_fm_config.rx_cfg.osc_freq;//MT6628fm_cust_config_fetch(FM_CFG_RX_OSC_FREQ);
+    osc_freq &= 0x0007; //rang 0~5
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_ENABLE_OPCODE;
+    pkt_size = 4;
+
+    //FM Digital Clock enable
+    pkt_size += fm_bop_write(0x60, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 60 0000
+    pkt_size += fm_bop_write(0x60, 0x0001, &buf[pkt_size], buf_size - pkt_size);//wr 60 0001
+    pkt_size += fm_bop_udelay(3000, &buf[pkt_size], buf_size - pkt_size);//delay 3ms
+    pkt_size += fm_bop_write(0x60, 0x0003, &buf[pkt_size], buf_size - pkt_size);//wr 60 0003
+    pkt_size += fm_bop_write(0x60, 0x0007, &buf[pkt_size], buf_size - pkt_size);//wr 60 0007
+    pkt_size += fm_bop_modify(0x70, 0xFFBF, 0x0040, &buf[pkt_size], buf_size - pkt_size); // wr 70 D6 = 1
+    //no low power mode, analog line in, long antenna
+    pkt_size += fm_bop_modify(0x61, 0xFF63, 0x0000, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_modify(0x61, ~DE_EMPHASIS, (de_emphasis << 12), &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_modify(0x60, OSC_FREQ_MASK, (osc_freq << 4), &buf[pkt_size], buf_size - pkt_size);
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+
+/*
+ * mt6628_patch_download - Wholechip FM Power Up: step 3, download patch to f/w,
+ * @buf - target buf
+ * @buf_size - buffer size
+ * @seg_num - total segments that this patch divided into
+ * @seg_id - No. of Segments: segment that will now be sent
+ * @src - patch source buffer
+ * @seg_len - segment size: segment that will now be sent
+ * return package size
+ */
+fm_s32 mt6628_patch_download(fm_u8 *buf, fm_s32 buf_size, fm_u8 seg_num, fm_u8 seg_id, const fm_u8 *src, fm_s32 seg_len)
+{
+    fm_s32 pkt_size = 0;
+    fm_u8 *dst = NULL;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_PATCH_DOWNLOAD_OPCODE;
+    pkt_size = 4;
+
+    buf[pkt_size++] = seg_num;
+    buf[pkt_size++] = seg_id;
+
+    if (seg_len > (buf_size - pkt_size)) {
+        return -1;
+    }
+
+    dst = &buf[pkt_size];
+    pkt_size += seg_len;
+
+    //copy patch to tx buffer
+    while (seg_len--) {
+        *dst = *src;
+        //printk(KERN_ALERT "%02x ", *dst);
+        src++;
+        dst++;
+    }
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+    WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
+
+    return pkt_size;
+}
+
+
+/*
+ * mt6628_coeff_download - Wholechip FM Power Up: step 3,download coeff to f/w,
+ * @buf - target buf
+ * @buf_size - buffer size
+ * @seg_num - total segments that this patch divided into
+ * @seg_id - No. of Segments: segment that will now be sent
+ * @src - patch source buffer
+ * @seg_len - segment size: segment that will now be sent
+ * return package size
+ */
+fm_s32 mt6628_coeff_download(fm_u8 *buf, fm_s32 buf_size, fm_u8 seg_num, fm_u8 seg_id, const fm_u8 *src, fm_s32 seg_len)
+{
+    fm_s32 pkt_size = 0;
+    fm_u8 *dst = NULL;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_COEFF_DOWNLOAD_OPCODE;
+    pkt_size = 4;
+
+    buf[pkt_size++] = seg_num;
+    buf[pkt_size++] = seg_id;
+
+    if (seg_len > (buf_size - pkt_size)) {
+        return -1;
+    }
+
+    dst = &buf[pkt_size];
+    pkt_size += seg_len;
+
+    //copy patch to tx buffer
+    while (seg_len--) {
+        *dst = *src;
+        //printk(KERN_ALERT "%02x ", *dst);
+        src++;
+        dst++;
+    }
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+    WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
+
+    return pkt_size;
+}
+
+
+/*
+ * mt6628_hwcoeff_download - Wholechip FM Power Up: step 3,download hwcoeff to f/w,
+ * @buf - target buf
+ * @buf_size - buffer size
+ * @seg_num - total segments that this patch divided into
+ * @seg_id - No. of Segments: segment that will now be sent
+ * @src - patch source buffer
+ * @seg_len - segment size: segment that will now be sent
+ * return package size
+ */
+fm_s32 mt6628_hwcoeff_download(fm_u8 *buf, fm_s32 buf_size, fm_u8 seg_num, fm_u8 seg_id, const fm_u8 *src, fm_s32 seg_len)
+{
+    fm_s32 pkt_size = 0;
+    fm_u8 *dst = NULL;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_HWCOEFF_DOWNLOAD_OPCODE;
+    pkt_size = 4;
+
+    buf[pkt_size++] = seg_num;
+    buf[pkt_size++] = seg_id;
+
+    if (seg_len > (buf_size - pkt_size)) {
+        return -1;
+    }
+
+    dst = &buf[pkt_size];
+    pkt_size += seg_len;
+
+    //copy patch to tx buffer
+    while (seg_len--) {
+        *dst = *src;
+        //printk(KERN_ALERT "%02x ", *dst);
+        src++;
+        dst++;
+    }
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+    WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
+
+    return pkt_size;
+}
+
+
+/*
+ * mt6628_rom_download - Wholechip FM Power Up: step 3,download rom to f/w,
+ * @buf - target buf
+ * @buf_size - buffer size
+ * @seg_num - total segments that this patch divided into
+ * @seg_id - No. of Segments: segment that will now be sent
+ * @src - patch source buffer
+ * @seg_len - segment size: segment that will now be sent
+ * return package size
+ */
+fm_s32 mt6628_rom_download(fm_u8 *buf, fm_s32 buf_size, fm_u8 seg_num, fm_u8 seg_id, const fm_u8 *src, fm_s32 seg_len)
+{
+    fm_s32 pkt_size = 0;
+    fm_u8 *dst = NULL;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_ROM_DOWNLOAD_OPCODE;
+    pkt_size = 4;
+
+    buf[pkt_size++] = seg_num;
+    buf[pkt_size++] = seg_id;
+
+    if (seg_len > (buf_size - pkt_size)) {
+        return -1;
+    }
+
+    dst = &buf[pkt_size];
+    pkt_size += seg_len;
+
+    //copy patch to tx buffer
+    while (seg_len--) {
+        *dst = *src;
+        //printk(KERN_ALERT "%02x ", *dst);
+        src++;
+        dst++;
+    }
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+    WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
+
+    return pkt_size;
+}
+
+
+/*
+ * mt6628_pwrup_digital_init - Wholechip FM Power Up: step 4, FM Digital Init: fm_rgf_maincon
+ * @buf - target buf
+ * @buf_size - buffer size
+ * return package size
+ */
+fm_s32 mt6628_pwrup_digital_init(fm_u8 *buf, fm_s32 buf_size)
+{
+    fm_s32 pkt_size = 0;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_ENABLE_OPCODE;
+    pkt_size = 4;
+
+    //Wholechip FM Power Up: FM Digital Init: fm_rgf_maincon
+    pkt_size += fm_bop_write(0x6A, 0x2100, &buf[pkt_size], buf_size - pkt_size);//wr 6A 2100
+    pkt_size += fm_bop_write(0x6B, 0x2100, &buf[pkt_size], buf_size - pkt_size);//wr 6B 2100
+    pkt_size += fm_bop_modify(0x60, 0xFFF7, 0x0008, &buf[pkt_size], buf_size - pkt_size);//wr 60 D3=1
+    pkt_size += fm_bop_modify(0x61, 0xFFFD, 0x0002, &buf[pkt_size], buf_size - pkt_size);//wr 61 D1=1
+    pkt_size += fm_bop_modify(0x61, 0xFFFE, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 61 D0=0
+    pkt_size += fm_bop_udelay(200000, &buf[pkt_size], buf_size - pkt_size);//delay 200ms
+    pkt_size += fm_bop_rd_until(0x64, 0x001F, 0x0002, &buf[pkt_size], buf_size - pkt_size);//Poll 64[0~4] = 2
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+
+/*
+ * mt6628_pwrdown - Wholechip FM Power down: Digital Modem Power Down
+ * @buf - target buf
+ * @buf_size - buffer size
+ * return package size
+ */
+fm_s32 mt6628_pwrdown(fm_u8 *buf, fm_s32 buf_size)
+{
+    fm_s32 pkt_size = 0;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_ENABLE_OPCODE;
+    pkt_size = 4;
+
+    //Disable HW clock control
+    pkt_size += fm_bop_write(0x60, 0x330F, &buf[pkt_size], buf_size - pkt_size);//wr 60 330F
+    //Reset ASIP
+    pkt_size += fm_bop_write(0x61, 0x0001, &buf[pkt_size], buf_size - pkt_size);//wr 61 0001
+    //digital core + digital rgf reset
+    pkt_size += fm_bop_modify(0x6E, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 6E[0~2] 0
+    pkt_size += fm_bop_modify(0x6E, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 6E[0~2] 0
+    pkt_size += fm_bop_modify(0x6E, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 6E[0~2] 0
+    pkt_size += fm_bop_modify(0x6E, 0xFFF8, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 6E[0~2] 0
+    //Disable all clock
+    pkt_size += fm_bop_write(0x60, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 60 0000
+    //Reset rgfrf
+    pkt_size += fm_bop_write(0x60, 0x4000, &buf[pkt_size], buf_size - pkt_size);//wr 60 4000
+    pkt_size += fm_bop_write(0x60, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 60 0000
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+
+/*
+ * mt6628_rampdown - f/w will wait for STC_DONE interrupt
+ * @buf - target buf
+ * @buf_size - buffer size
+ * return package size
+ */
+fm_s32 mt6628_rampdown(fm_u8 *buf, fm_s32 buf_size)
+{
+    fm_s32 pkt_size = 0;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_RAMPDOWN_OPCODE;
+    pkt_size = 4;
+
+    //Clear DSP state
+    pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFF0, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 63[3:0] = 0
+    //Set DSP ramp down state
+    pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFFF, RAMP_DOWN, &buf[pkt_size], buf_size - pkt_size);//wr 63[8] = 1
+    //@Wait for STC_DONE interrupt@
+    pkt_size += fm_bop_rd_until(FM_MAIN_INTR, FM_INTR_STC_DONE, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//Poll 69[0] = b'1
+    //Clear DSP ramp down state
+    pkt_size += fm_bop_modify(FM_MAIN_CTRL, (~RAMP_DOWN), 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 63[8] = 0
+    //Write 1 clear the STC_DONE interrupt status flag
+    pkt_size += fm_bop_modify(FM_MAIN_INTR, 0xFFFF, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//wr 69[0] = 1
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+
+/*
+ * mt6628_tune - execute tune action,
+ * @buf - target buf
+ * @buf_size - buffer size
+ * @freq - 760 ~ 1080, 100KHz unit
+ * return package size
+ */
+fm_s32 mt6628_tune(fm_u8 *buf, fm_s32 buf_size, fm_u16 freq, fm_u16 chan_para)
+{
+    //#define FM_TUNE_USE_POLL
+    fm_s32 pkt_size = 0;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    if (0 == fm_get_channel_space(freq)) {
+        freq *= 10;
+    }
+    
+    freq = (freq - 6400) * 2 / 10;
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_TUNE_OPCODE;
+    pkt_size = 4;
+
+    //Set desired channel & channel parameter
+#ifdef FM_TUNE_USE_POLL
+    pkt_size += fm_bop_write(0x6A, 0x0000, &buf[pkt_size], buf_size - pkt_size);
+    pkt_size += fm_bop_write(0x6B, 0x0000, &buf[pkt_size], buf_size - pkt_size);
+#endif
+    pkt_size += fm_bop_modify(FM_CHANNEL_SET, 0xFC00, freq, &buf[pkt_size], buf_size - pkt_size);// set 0x65[9:0] = 0x029e, => ((97.5 - 64) * 20)
+    //channel para setting, D15~D12, D15: ATJ, D13: HL, D12: FA
+    pkt_size += fm_bop_modify(FM_CHANNEL_SET, 0x0FFF, (chan_para << 12), &buf[pkt_size], buf_size - pkt_size);
+    //Enable hardware controlled tuning sequence
+    pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFF8, TUNE, &buf[pkt_size], buf_size - pkt_size);// set 0x63[0] = 1
+    //Wait for STC_DONE interrupt
+#ifdef FM_TUNE_USE_POLL
+    pkt_size += fm_bop_rd_until(FM_MAIN_INTR, FM_INTR_STC_DONE, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//Poll 69[0] = b'1
+    //Write 1 clear the STC_DONE interrupt status flag
+    pkt_size += fm_bop_modify(FM_MAIN_INTR, 0xFFFF, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//wr 69[0] = 1
+#endif
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+
+/*
+ * mt6628_full_cqi_req - execute request cqi info action,
+ * @buf - target buf
+ * @buf_size - buffer size
+ * @freq - 7600 ~ 10800, freq array
+ * @cnt - channel count
+ * @type - request type, 1: a single channel; 2: multi channel; 3:multi channel with 100Khz step; 4: multi channel with 50Khz step
+ * 
+ * return package size
+ */
+fm_s32 mt6628_full_cqi_req(fm_u8 *buf, fm_s32 buf_size, fm_u16 *freq, fm_s32 cnt, fm_s32 type)
+{
+    fm_s32 pkt_size = 0;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_SOFT_MUTE_TUNE_OPCODE;
+    pkt_size = 4;
+
+    switch (type) {
+        case 1:
+            buf[pkt_size] = 0x0001;
+            pkt_size++;
+            buf[pkt_size] = (fm_u8)((*freq) & 0x00FF);
+            pkt_size++;
+            buf[pkt_size] = (fm_u8)((*freq >> 8) & 0x00FF);
+            pkt_size++;
+            break;
+        case 2:
+            buf[pkt_size] = 0x0002;
+            pkt_size++;
+            break;
+        case 3:
+            buf[pkt_size] = 0x0003;
+            pkt_size++;
+            break;
+        case 4:
+            buf[pkt_size] = 0x0004;
+            pkt_size++;
+            break;
+        default:
+            buf[pkt_size] = (fm_u16)type;
+            pkt_size++;
+            break;
+    }
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+
+/*
+ * mt6628_seek - execute seek action,
+ * @buf - target buf
+ * @buf_size - buffer size
+ * @seekdir - 0=seek up, 1=seek down
+ * @space - step, 50KHz:001, 100KHz:010, 200KHz:100
+ * @max_freq - upper bound
+ * @min_freq - lower bound
+ * return package size
+ */
+fm_s32 mt6628_seek(fm_u8 *buf, fm_s32 buf_size, fm_u16 seekdir, fm_u16 space, fm_u16 max_freq, fm_u16 min_freq)
+{
+    fm_s32 pkt_size = 0;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    if (0 == fm_get_channel_space(max_freq)) {
+        max_freq *= 10;
+    }
+
+    if (0 == fm_get_channel_space(min_freq)) {
+        min_freq *= 10;
+    }
+    
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_SEEK_OPCODE;
+    pkt_size = 4;
+
+    //Program seek direction
+    if (seekdir == 0) {
+        pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xFBFF, 0x0000, &buf[pkt_size], buf_size - pkt_size);//0x66[10] = 0, seek up
+    } else {
+        pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xFBFF, 0x0400, &buf[pkt_size], buf_size - pkt_size);//0x66[10] = 1, seek down
+    }
+
+    //Program scan channel spacing
+    if (space == 1) {
+        pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0x8FFF, 0x1000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=001
+    } else if (space == 2) {
+        pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0x8FFF, 0x2000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=010
+    } else if (space == 4) {
+        pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0x8FFF, 0x4000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=100
+    }
+
+    //enable wrap , if it is not auto scan function, 0x66[11] 0=no wrarp, 1=wrap
+    pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xF7FF, 0x0800, &buf[pkt_size], buf_size - pkt_size);//0x66[11] = 1, wrap
+    //0x66[9:0] freq upper bound
+
+    max_freq = (max_freq - 6400) * 2 / 10;
+
+    pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xFC00, max_freq, &buf[pkt_size], buf_size - pkt_size);
+    //0x67[9:0] freq lower bound
+
+    min_freq = (min_freq - 6400) * 2 / 10;
+
+    pkt_size += fm_bop_modify(FM_MAIN_CFG2, 0xFC00, min_freq, &buf[pkt_size], buf_size - pkt_size);
+    //Enable hardware controlled seeking sequence
+    pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFF8, SEEK, &buf[pkt_size], buf_size - pkt_size);//0x63[1] = 1
+    //Wait for STC_DONE interrupt
+    //pkt_size += fm_bop_rd_until(FM_MAIN_INTR, FM_INTR_STC_DONE, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//Poll 69[0] = b'1
+    //Write 1 clear the STC_DONE interrupt status flag
+    //pkt_size += fm_bop_modify(FM_MAIN_INTR, 0xFFFF, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//wr 69[0] = 1
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+
+/*
+ * mt6628_scan - execute scan action,
+ * @buf - target buf
+ * @buf_size - buffer size
+ * @scandir - 0=seek up, 1=seek down
+ * @space - step, 50KHz:001, 100KHz:010, 200KHz:100
+ * @max_freq - upper bound
+ * @min_freq - lower bound
+ * return package size
+ */
+fm_s32 mt6628_scan(fm_u8 *buf, fm_s32 buf_size, fm_u16 scandir, fm_u16 space, fm_u16 max_freq, fm_u16 min_freq)
+{
+    fm_s32 pkt_size = 0;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    if (0 == fm_get_channel_space(max_freq)) {
+        max_freq *= 10;
+    }
+    if (0 == fm_get_channel_space(min_freq)) {
+        min_freq *= 10;
+    }
+    
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_SCAN_OPCODE;
+    pkt_size = 4;
+
+    //Program seek direction
+    if (scandir == 0) {
+        pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xFBFF, 0x0000, &buf[pkt_size], buf_size - pkt_size);//0x66[10] = 0, seek up
+    } else {
+        pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xFFFF, 0x0400, &buf[pkt_size], buf_size - pkt_size);//0x66[10] = 1, seek down
+    }
+
+    //Program scan channel spacing
+    if (space == 1) {
+        pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0x8FFF, 0x1000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=001
+    } else if (space == 2) {
+        pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0x8FFF, 0x2000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=010
+    } else if (space == 4) {
+        pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0x8FFF, 0x4000, &buf[pkt_size], buf_size - pkt_size);//clear 0x66[14:12] then 0x66[14:12]=100
+    }
+
+    //disable wrap , if it is auto scan function, 0x66[11] 0=no wrarp, 1=wrap
+    pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xF7FF, 0x0000, &buf[pkt_size], buf_size - pkt_size);//0x66[11] = 0, no wrap
+    //0x66[9:0] freq upper bound
+
+    max_freq = (max_freq - 6400) * 2 / 10;
+
+    pkt_size += fm_bop_modify(FM_MAIN_CFG1, 0xFC00, max_freq, &buf[pkt_size], buf_size - pkt_size);
+    //0x67[9:0] freq lower bound
+
+    min_freq = (min_freq - 6400) * 2 / 10;
+
+    pkt_size += fm_bop_modify(FM_MAIN_CFG2, 0xFC00, min_freq, &buf[pkt_size], buf_size - pkt_size);
+    //Enable hardware controlled scanning sequence
+    pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFF8, SCAN, &buf[pkt_size], buf_size - pkt_size);//0x63[1] = 1
+    //Wait for STC_DONE interrupt
+    //pkt_size += fm_bop_rd_until(FM_MAIN_INTR, FM_INTR_STC_DONE, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//Poll 69[0] = b'1
+    //Write 1 clear the STC_DONE interrupt status flag
+    //pkt_size += fm_bop_modify(FM_MAIN_INTR, 0xFFFF, FM_INTR_STC_DONE, &buf[pkt_size], buf_size - pkt_size);//wr 69[0] = 1
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+
+fm_s32 mt6628_cqi_get(fm_u8 *buf, fm_s32 buf_size)
+{
+    fm_s32 pkt_size = 0;
+
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FM_SCAN_OPCODE;
+    pkt_size = 4;
+
+    pkt_size += fm_bop_modify(FM_MAIN_CTRL, 0xFFF0, 0x0000, &buf[pkt_size], buf_size - pkt_size);//wr 63 bit0~2 0
+    pkt_size += fm_bop_modify(FM_MAIN_CTRL, ~CQI_READ, CQI_READ, &buf[pkt_size], buf_size - pkt_size);//wr 63 bit3 1
+
+    buf[2] = (fm_u8)((pkt_size - 4) & 0x00FF);
+    buf[3] = (fm_u8)(((pkt_size - 4) >> 8) & 0x00FF);
+
+    return pkt_size;
+}
+
+
+fm_s32 mt6628_get_reg(fm_u8 *buf, fm_s32 buf_size, fm_u8 addr)
+{
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FSPI_READ_OPCODE;
+    buf[2] = 0x01;
+    buf[3] = 0x00;
+    buf[4] = addr;
+
+    WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4]);
+    return 5;
+}
+
+
+fm_s32 mt6628_set_reg(fm_u8 *buf, fm_s32 buf_size, fm_u8 addr, fm_u16 value)
+{
+    if (buf_size < TX_BUF_SIZE) {
+        return (-1);
+    }
+
+    buf[0] = FM_TASK_COMMAND_PKT_TYPE;
+    buf[1] = FSPI_WRITE_OPCODE;
+    buf[2] = 0x03;
+    buf[3] = 0x00;
+    buf[4] = addr;
+    buf[5] = (fm_u8)((value) & 0x00FF);
+    buf[6] = (fm_u8)((value >> 8) & 0x00FF);
+
+    WCN_DBG(FM_DBG | CHIP, "%02x %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
+    return 7;
+}
+
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6628/pub/mt6628_fm_config.c b/drivers/mtk_wcn_combo/drv_fm/mt6628/pub/mt6628_fm_config.c
new file mode 100755 (executable)
index 0000000..002000c
--- /dev/null
@@ -0,0 +1,279 @@
+/* fm_config.c
+ *
+ * (C) Copyright 2011
+ * MediaTek <www.MediaTek.com>
+ * hongcheng <hongcheng.xia@MediaTek.com>
+ *
+ * FM Radio Driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "fm_typedef.h"
+#include "fm_rds.h"
+#include "fm_dbg.h"
+#include "fm_err.h"
+#include "fm_stdlib.h"
+#include "fm_patch.h"
+#include "fm_config.h"
+//#include "fm_cust_cfg.h"
+#include "mt6628_fm_cust_cfg.h"
+fm_cust_cfg mt6628_fm_config;
+//static fm_s32 fm_index = 0;
+
+static fm_s32 MT6628fm_cust_config_print(fm_cust_cfg *cfg)
+{
+    WCN_DBG(FM_NTC | MAIN, "MT6628 rssi_l:\t%d\n", cfg->rx_cfg.long_ana_rssi_th);
+    WCN_DBG(FM_NTC | MAIN, "MT6628 rssi_s:\t%d\n", cfg->rx_cfg.short_ana_rssi_th);
+    WCN_DBG(FM_NTC | MAIN, "MT6628 pamd_th:\t%d\n", cfg->rx_cfg.pamd_th);
+    WCN_DBG(FM_NTC | MAIN, "MT6628 mr_th:\t%d\n", cfg->rx_cfg.mr_th);
+    WCN_DBG(FM_NTC | MAIN, "MT6628 atdc_th:\t%d\n", cfg->rx_cfg.atdc_th);
+    WCN_DBG(FM_NTC | MAIN, "MT6628 prx_th:\t%d\n", cfg->rx_cfg.prx_th);
+    WCN_DBG(FM_NTC | MAIN, "MT6628 atdev_th:\t%d\n", cfg->rx_cfg.atdev_th);
+    WCN_DBG(FM_NTC | MAIN, "MT6628 smg_th:\t%d\n", cfg->rx_cfg.smg_th);
+    WCN_DBG(FM_NTC | MAIN, "de_emphasis:\t%d\n", cfg->rx_cfg.deemphasis);
+    WCN_DBG(FM_NTC | MAIN, "osc_freq:\t%d\n", cfg->rx_cfg.osc_freq);
+
+    return 0;
+}
+
+static fm_s32 MT6628cfg_item_handler(fm_s8 *grp, fm_s8 *key, fm_s8 *val, fm_cust_cfg *cfg)
+{
+    fm_s32 ret = 0;
+    struct fm_rx_cust_cfg *rx_cfg = &cfg->rx_cfg;
+
+    if (0 <= (ret = cfg_item_match(key, val, "FM_RX_RSSI_TH_LONG_MT6628", &rx_cfg->long_ana_rssi_th))) 
+    {//FMR_RSSI_TH_L = 0x0301
+        return ret;
+    } 
+    else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_RSSI_TH_SHORT_MT6628", &rx_cfg->short_ana_rssi_th))) 
+    {
+        return ret;
+    } 
+    else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_DESENSE_RSSI_MT6628", &rx_cfg->desene_rssi_th))) 
+    {
+        return ret;
+    } 
+    else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_PAMD_TH_MT6628", &rx_cfg->pamd_th))) 
+    {
+        return ret;
+    } 
+    else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_MR_TH_MT6628", &rx_cfg->mr_th))) 
+    {
+        return ret;
+    } 
+    else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_ATDC_TH_MT6628", &rx_cfg->atdc_th))) 
+    {
+        return ret;
+    } 
+    else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_PRX_TH_MT6628", &rx_cfg->prx_th))) 
+    {
+        return ret;
+    } 
+    /*else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_ATDEV_TH_MT6628", &rx_cfg->atdev_th))) 
+    {
+        return ret;
+    } */
+    else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_SMG_TH_MT6628", &rx_cfg->smg_th))) 
+    {
+        return ret;
+    } 
+    else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_DEEMPHASIS_MT6628", &rx_cfg->deemphasis))) 
+    {
+        return ret;
+    } 
+    else if (0 <= (ret = cfg_item_match(key, val, "FM_RX_OSC_FREQ_MT6628", &rx_cfg->osc_freq))) 
+    {
+        return ret;
+    } 
+    else 
+    {
+        WCN_DBG(FM_WAR | MAIN, "MT6628 invalid key\n");
+        return -1;
+    }
+}
+
+static fm_s32 MT6628fm_cust_config_default(fm_cust_cfg *cfg)
+{
+    FMR_ASSERT(cfg);
+
+    cfg->rx_cfg.long_ana_rssi_th = FM_RX_RSSI_TH_LONG_MT6628;
+    cfg->rx_cfg.short_ana_rssi_th = FM_RX_RSSI_TH_SHORT_MT6628;
+    cfg->rx_cfg.desene_rssi_th = FM_RX_DESENSE_RSSI_MT6628;
+    cfg->rx_cfg.pamd_th = FM_RX_PAMD_TH_MT6628;
+    cfg->rx_cfg.mr_th = FM_RX_MR_TH_MT6628;
+    cfg->rx_cfg.atdc_th = FM_RX_ATDC_TH_MT6628;
+    cfg->rx_cfg.prx_th = FM_RX_PRX_TH_MT6628;
+    cfg->rx_cfg.smg_th = FM_RX_SMG_TH_MT6628;
+    cfg->rx_cfg.deemphasis = FM_RX_DEEMPHASIS_MT6628;
+       cfg->rx_cfg.osc_freq = FM_RX_OSC_FREQ_MT6628;
+
+    return 0;
+}
+
+static fm_s32 MT6628fm_cust_config_file(const fm_s8 *filename, fm_cust_cfg *cfg)
+{
+    fm_s32 ret = 0;
+    fm_s8 *buf = NULL;
+    fm_s32 file_len = 0;
+
+    if (!(buf = fm_zalloc(4096))) {
+        WCN_DBG(FM_ALT | MAIN, "-ENOMEM\n");
+        return -ENOMEM;
+    }
+
+//    fm_index = 0;
+
+    file_len = fm_file_read(filename, buf, 4096, 0);
+
+    if (file_len <= 0) {
+        ret = -1;
+        goto out;
+    }
+
+    ret = cfg_parser(buf, MT6628cfg_item_handler, cfg);
+
+out:
+
+    if (buf) {
+        fm_free(buf);
+    }
+
+    return ret;
+}
+#define MT6628_FM_CUST_CFG_PATH "etc/fmr/fm_cust.cfg"
+fm_s32 MT6628fm_cust_config_setup(const fm_s8 *filepath)
+{
+    fm_s32 ret = 0;
+    fm_s8 *filep = NULL;
+    fm_s8 file_path[51] = {0};
+
+    MT6628fm_cust_config_default(&mt6628_fm_config);
+    WCN_DBG(FM_NTC | MAIN, "MT6628 FM default config\n");
+    MT6628fm_cust_config_print(&mt6628_fm_config);
+       
+    if (!filepath) {
+        filep = MT6628_FM_CUST_CFG_PATH;
+    } else {
+        memcpy(file_path, filepath, (strlen(filepath) > 50) ? 50 : strlen(filepath));
+        filep = file_path;
+        trim_path(&filep);
+    }
+
+    ret = MT6628fm_cust_config_file(filep, &mt6628_fm_config);
+    WCN_DBG(FM_NTC | MAIN, "MT6628 FM cust config\n");
+    MT6628fm_cust_config_print(&mt6628_fm_config);
+       
+    return ret;
+}
+fm_u16 MT6628fm_cust_config_fetch(enum fm_cust_cfg_op op_code)
+{
+#if 0
+    fm_u16 tmp = 0;
+    fm_s32 i;
+    static fm_s32 fake_ch_idx = 0;
+
+    switch (op_code) {
+        //For FM RX
+    case FM_CFG_RX_RSSI_TH_LONG: {
+        tmp = mt6628_fm_config.rx_cfg.long_ana_rssi_th;
+        break;
+    }
+    case FM_CFG_RX_RSSI_TH_SHORT: {
+        tmp = mt6628_fm_config.rx_cfg.short_ana_rssi_th;
+        break;
+    }
+    case FM_CFG_RX_CQI_TH: {
+        tmp = mt6628_fm_config.rx_cfg.cqi_th;
+        break;
+    }
+    case FM_CFG_RX_MR_TH: {
+        tmp = mt6628_fm_config.rx_cfg.mr_th;
+        break;
+    }
+    case FM_CFG_RX_SMG_TH: {
+        tmp = mt6628_fm_config.rx_cfg.smg_th;
+        break;
+    }
+    case FM_CFG_RX_SCAN_CH_SIZE: {
+        tmp = mt6628_fm_config.rx_cfg.scan_ch_size;
+        break;
+    }
+    case FM_CFG_RX_SEEK_SPACE: {
+        tmp = mt6628_fm_config.rx_cfg.seek_space;
+        break;
+    }
+    case FM_CFG_RX_BAND: {
+        tmp = mt6628_fm_config.rx_cfg.band;
+        break;
+    }
+    case FM_CFG_RX_BAND_FREQ_L: {
+        tmp = mt6628_fm_config.rx_cfg.band_freq_l;
+        break;
+    }
+    case FM_CFG_RX_BAND_FREQ_H: {
+        tmp = mt6628_fm_config.rx_cfg.band_freq_h;
+        break;
+    }
+    case FM_CFG_RX_SCAN_SORT: {
+        tmp = mt6628_fm_config.rx_cfg.scan_sort;
+        break;
+    }
+    case FM_CFG_RX_FAKE_CH_NUM: {
+        tmp = mt6628_fm_config.rx_cfg.fake_ch_num;
+        break;
+    }
+    case FM_CFG_RX_FAKE_CH: {
+        tmp = mt6628_fm_config.rx_cfg.fake_ch[fake_ch_idx];
+        i = (mt6628_fm_config.rx_cfg.fake_ch_num > 0) ? mt6628_fm_config.rx_cfg.fake_ch_num : FAKE_CH_MAX;
+        fake_ch_idx++;
+        fake_ch_idx = fake_ch_idx % i;
+        break;
+    }
+    case FM_CFG_RX_FAKE_CH_RSSI: {
+        tmp = mt6628_fm_config.rx_cfg.fake_ch_rssi_th;
+        break;
+    }
+    case FM_CFG_RX_DEEMPHASIS: {
+        tmp = mt6628_fm_config.rx_cfg.deemphasis;
+        break;
+    }
+    case FM_CFG_RX_OSC_FREQ: {
+        tmp = mt6628_fm_config.rx_cfg.osc_freq;
+        break;
+    }
+    //For FM TX
+    case FM_CFG_TX_SCAN_HOLE_LOW: {
+        tmp = mt6628_fm_config.tx_cfg.scan_hole_low;
+        break;
+    }
+    case FM_CFG_TX_SCAN_HOLE_HIGH: {
+        tmp = mt6628_fm_config.tx_cfg.scan_hole_high;
+        break;
+    }
+    case FM_CFG_TX_PWR_LEVEL: {
+        tmp = mt6628_fm_config.tx_cfg.power_level;
+        break;
+    }
+    default:
+        break;
+    }
+
+    WCN_DBG(FM_DBG | MAIN, "mt6628_cust cfg %d: 0x%04x\n", op_code, tmp);
+#endif
+    return 0;
+}
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6628/pub/mt6628_fm_eint.c b/drivers/mtk_wcn_combo/drv_fm/mt6628/pub/mt6628_fm_eint.c
new file mode 100755 (executable)
index 0000000..4e69b9e
--- /dev/null
@@ -0,0 +1,55 @@
+/* mt6628_fm_eint.c
+ *
+ * (C) Copyright 2009 
+ * MediaTek <www.MediaTek.com>
+ * Hongcheng <hongcheng.xia@MediaTek.com>
+ *
+ * MT6628 FM Radio Driver -- EINT functions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#if 0
+#include "stp_exp.h"
+#include "wmt_exp.h"
+
+#include "fm_typedef.h"
+#include "fm_dbg.h"
+#include "fm_err.h"
+#include "fm_eint.h"
+       
+fm_s32 fm_enable_eint(void)
+{
+       return 0;
+}
+
+fm_s32 fm_disable_eint(void)
+{
+       return 0;
+}
+
+fm_s32 fm_request_eint(void (*parser)(void))
+{
+    WCN_DBG(FM_NTC|EINT,"%s\n", __func__);
+
+    mtk_wcn_stp_register_event_cb(FM_TASK_INDX, parser);
+    
+       return 0;
+}
+
+fm_s32 fm_eint_pin_cfg(fm_s32 mode)
+{      
+       return 0;
+}
+#endif
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6628/pub/mt6628_fm_lib.c b/drivers/mtk_wcn_combo/drv_fm/mt6628/pub/mt6628_fm_lib.c
new file mode 100755 (executable)
index 0000000..e101b7a
--- /dev/null
@@ -0,0 +1,1741 @@
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+
+#include "stp_exp.h"
+#include "wmt_exp.h"
+
+#include "fm_typedef.h"
+#include "fm_dbg.h"
+#include "fm_err.h"
+#include "fm_interface.h"
+#include "fm_stdlib.h"
+#include "fm_patch.h"
+#include "fm_utils.h"
+#include "fm_link.h"
+#include "fm_config.h"
+#include "fm_private.h"
+
+#include "mt6628_fm_reg.h"
+#include "mt6628_fm.h"
+//#include "mt6628_drv_dsp.h"
+//#include "mt6628_fm_link.h"
+#include "mt6628_fm_lib.h"
+#include "mt6628_fm_cmd.h"
+#include "mt6628_fm_cust_cfg.h"
+extern fm_cust_cfg mt6628_fm_config;
+
+#define MT6628_FM_PATCH_PATH "/etc/firmware/mt6628/mt6628_fm_patch.bin"
+#define MT6628_FM_COEFF_PATH "/etc/firmware/mt6628/mt6628_fm_coeff.bin"
+#define MT6628_FM_HWCOEFF_PATH "/etc/firmware/mt6628/mt6628_fm_hwcoeff.bin"
+#define MT6628_FM_ROM_PATH "/etc/firmware/mt6628/mt6628_fm_rom.bin"
+
+static struct fm_patch_tbl mt6628_patch_tbl[5] = {
+    {FM_ROM_V1, "/etc/firmware/mt6628/mt6628_fm_v1_patch.bin", "/etc/firmware/mt6628/mt6628_fm_v1_coeff.bin", NULL, NULL},
+    {FM_ROM_V2, "/etc/firmware/mt6628/mt6628_fm_v2_patch.bin", "/etc/firmware/mt6628/mt6628_fm_v2_coeff.bin", NULL, NULL},
+    {FM_ROM_V3, "/etc/firmware/mt6628/mt6628_fm_v3_patch.bin", "/etc/firmware/mt6628/mt6628_fm_v3_coeff.bin", NULL, NULL},
+    {FM_ROM_V4, "/etc/firmware/mt6628/mt6628_fm_v4_patch.bin", "/etc/firmware/mt6628/mt6628_fm_v4_coeff.bin", NULL, NULL},
+    {FM_ROM_V5, "/etc/firmware/mt6628/mt6628_fm_v5_patch.bin", "/etc/firmware/mt6628/mt6628_fm_v5_coeff.bin", NULL, NULL},
+};
+
+static struct fm_hw_info mt6628_hw_info = {
+    .chip_id = 0x00006628,
+    .eco_ver = 0x00000000,
+    .rom_ver = 0x00000000,
+    .patch_ver = 0x00000000,
+    .reserve = 0x00000000,
+};
+
+static struct fm_i2s_info mt6628_i2s_inf = {
+    .status = 0,    //i2s off
+    .mode = 0,      //slave mode
+    .rate = 48000,  //48000 sample rate
+};
+
+#define PATCH_SEG_LEN 512
+
+static fm_u8 *cmd_buf = NULL;
+static struct fm_lock *cmd_buf_lock = NULL;
+static struct fm_callback *fm_cb_op;
+static struct fm_res_ctx *res = NULL;
+//static fm_s32 Chip_Version = mt6628_E1;
+
+//static fm_bool rssi_th_set = fm_false;
+
+#ifdef MT6628_FM_FPGA
+#undef MT6628_FM_USE_6626EVB
+#endif
+
+#ifdef MTK_FM_50KHZ_SUPPORT
+static struct fm_fifo *cqi_fifo = NULL;
+#endif
+static fm_s32 mt6628_is_dese_chan(fm_u16 freq);
+static fm_s32 mt6628_mcu_dese(fm_u16 freq, void *arg);
+static fm_s32 mt6628_gps_dese(fm_u16 freq, void *arg);
+static fm_u16 mt6628_chan_para_get(fm_u16 freq);
+static fm_s32 mt6628_desense_check(fm_u16 freq,fm_s32 rssi);
+static fm_s32 mt6628_I2s_Setting(fm_s32 onoff, fm_s32 mode, fm_s32 sample);
+static fm_s32 mt6628_soft_mute_tune(fm_u16 freq,fm_s32 *rssi,fm_bool *valid);
+static fm_s32 mt6628_pwron(fm_s32 data)
+{
+    /*//Turn on FM on 6628 chip by WMT driver
+    if(MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_LPBK)){
+        WCN_DBG(FM_ALT|CHIP,"WMT turn on LPBK Fail!\n");
+        return -FM_ELINK;
+    }else{
+        WCN_DBG(FM_ALT|CHIP,"WMT turn on LPBK OK!\n");
+        //return 0;
+    }*/
+    if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_FM)) {
+        WCN_DBG(FM_ALT | CHIP, "WMT turn on FM Fail!\n");
+        return -FM_ELINK;
+    } else {
+        WCN_DBG(FM_ALT | CHIP, "WMT turn on FM OK!\n");
+        return 0;
+    }
+}
+
+
+static fm_s32 mt6628_pwroff(fm_s32 data)
+{
+    if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_off(WMTDRV_TYPE_FM)) {
+        WCN_DBG(FM_ALT | CHIP, "WMT turn off FM Fail!\n");
+        return -FM_ELINK;
+    } else {
+        WCN_DBG(FM_NTC | CHIP, "WMT turn off FM OK!\n");
+        return 0;
+    }
+}
+
+static fm_s32 Delayms(fm_u32 data)
+{
+    WCN_DBG(FM_DBG | CHIP, "delay %dms\n", data);
+    msleep(data);
+    return 0;
+}
+
+static fm_s32 Delayus(fm_u32 data)
+{
+    WCN_DBG(FM_DBG | CHIP, "delay %dus\n", data);
+    udelay(data);
+    return 0;
+}
+
+fm_s32 mt6628_get_read_result(struct fm_res_ctx* result)
+{
+    FMR_ASSERT(result);
+    res = result;
+
+    return 0;
+}
+
+static fm_s32 mt6628_read(fm_u8 addr, fm_u16 *val)
+{
+    fm_s32 ret = 0;
+    fm_u16 pkt_size;
+
+    if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK);
+    pkt_size = mt6628_get_reg(cmd_buf, TX_BUF_SIZE, addr);
+    ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_FSPI_RD, SW_RETRY_CNT, FSPI_RD_TIMEOUT, mt6628_get_read_result);
+
+    if (!ret && res) {
+        *val = res->fspi_rd;
+    }
+
+    FM_UNLOCK(cmd_buf_lock);
+
+    return ret;
+}
+
+static fm_s32 mt6628_write(fm_u8 addr, fm_u16 val)
+{
+    fm_s32 ret = 0;
+    fm_u16 pkt_size;
+
+    if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK);
+    pkt_size = mt6628_set_reg(cmd_buf, TX_BUF_SIZE, addr, val);
+    ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_FSPI_WR, SW_RETRY_CNT, FSPI_WR_TIMEOUT, NULL);
+    FM_UNLOCK(cmd_buf_lock);
+
+    return ret;
+}
+
+static fm_s32 mt6628_set_bits(fm_u8 addr, fm_u16 bits, fm_u16 mask)
+{
+    fm_s32 ret = 0;
+    fm_u16 val;
+
+    ret = mt6628_read(addr, &val);
+
+    if (ret)
+        return ret;
+
+    val = ((val & (mask)) | bits);
+    ret = mt6628_write(addr, val);
+
+    return ret;
+}
+
+static fm_u16 mt6628_get_chipid(void)
+{
+    return 0x6628;
+}
+
+/*  MT6628_SetAntennaType - set Antenna type
+ *  @type - 1,Short Antenna;  0, Long Antenna
+ */
+static fm_s32 mt6628_SetAntennaType(fm_s32 type)
+{
+    fm_u16 dataRead;
+
+    WCN_DBG(FM_DBG | CHIP, "set ana to %s\n", type ? "short" : "long");
+    mt6628_read(FM_MAIN_CG2_CTRL, &dataRead);
+
+    if (type) {
+        dataRead |= ANTENNA_TYPE;
+    } else {
+        dataRead &= (~ANTENNA_TYPE);
+    }
+
+    mt6628_write(FM_MAIN_CG2_CTRL, dataRead);
+
+    return 0;
+}
+
+static fm_s32 mt6628_GetAntennaType(void)
+{
+    fm_u16 dataRead;
+
+    mt6628_read(FM_MAIN_CG2_CTRL, &dataRead);
+    WCN_DBG(FM_DBG | CHIP, "get ana type: %s\n", (dataRead&ANTENNA_TYPE) ? "short" : "long");
+
+    if (dataRead&ANTENNA_TYPE)
+        return FM_ANA_SHORT; //short antenna
+    else
+        return FM_ANA_LONG; //long antenna
+}
+
+
+static fm_s32 mt6628_Mute(fm_bool mute)
+{
+    fm_s32 ret = 0;
+    fm_u16 dataRead;
+
+    WCN_DBG(FM_DBG | CHIP, "set %s\n", mute ? "mute" : "unmute");
+    mt6628_read(FM_MAIN_CTRL, &dataRead);
+
+    if (mute == 1) {
+        ret = mt6628_write(FM_MAIN_CTRL, (dataRead&0xFFDF) | 0x0020);
+    } else {
+        ret = mt6628_write(FM_MAIN_CTRL, (dataRead&0xFFDF));
+}
+
+    return ret;
+}
+
+
+/*static fm_s32 mt6628_set_RSSITh(fm_u16 TH_long, fm_u16 TH_short)
+{
+    mt6628_write(0xE2, 0x3072);
+    mt6628_write(0xE3, TH_long);
+    mt6628_write(0xE1, 0x0002);
+    Delayms(1);
+    mt6628_write(0xE2, 0x307A);
+    mt6628_write(0xE3, TH_short);
+    mt6628_write(0xE1, 0x0002);
+
+    WCN_DBG(FM_DBG | CHIP, "RSSI TH, long:0x%04x, short:0x%04x", TH_long, TH_short);
+    return 0;
+}
+*/
+/*
+static fm_s32 mt6628_set_SMGTh(fm_s32 ver, fm_u16 TH_smg)
+{
+    if (mt6628_E1 == ver) {
+        mt6628_write(0xE2, 0x321E);
+        mt6628_write(0xE3, TH_smg);
+        mt6628_write(0xE1, 0x0002);
+    } else {
+        mt6628_write(0xE2, 0x3218);
+        mt6628_write(0xE3, TH_smg);
+        mt6628_write(0xE1, 0x0002);
+    }
+
+    WCN_DBG(FM_DBG | CHIP, "Soft-mute gain TH %d\n", (int)TH_smg);
+    return 0;
+}
+*/
+static fm_s32 mt6628_RampDown(void)
+{
+    fm_s32 ret = 0;
+    fm_u16 pkt_size;
+    fm_u16 tmp;
+
+    WCN_DBG(FM_DBG | CHIP, "ramp down\n");
+
+    mt6628_read(FM_MAIN_INTRMASK, &tmp);
+    mt6628_write(FM_MAIN_INTRMASK, 0x0000);
+    mt6628_write(0x6B, 0x0000);
+
+    if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK);
+    pkt_size = mt6628_rampdown(cmd_buf, TX_BUF_SIZE);
+    ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_RAMPDOWN, SW_RETRY_CNT, RAMPDOWN_TIMEOUT, NULL);
+    FM_UNLOCK(cmd_buf_lock);
+
+    if (ret) {
+        WCN_DBG(FM_ERR | CHIP, "ramp down failed\n");
+    }
+
+#ifdef MT6628_FM_FPGA
+    Delayms(10);
+    mt6628_write(0x54, 0x0001);
+    mt6628_write(0x11, 0x37D4);
+    mt6628_write(0x54, 0x8000);
+#endif
+    mt6628_write(0x6B, 0x2100);
+    mt6628_write(FM_MAIN_INTRMASK, tmp);
+    return ret;
+}
+
+static fm_s32 mt6628_get_rom_version(void)
+{
+    fm_u16 tmp;
+
+    //DSP rom code version request enable --- set 0x61 b15=1
+    mt6628_set_bits(0x61, 0x8000, 0x7FFF);
+
+    //Release ASIP reset --- set 0x61 b1=1
+    mt6628_set_bits(0x61, 0x0002, 0xFFFD);
+
+    //Enable ASIP power --- set 0x61 b0=0
+    mt6628_set_bits(0x61, 0x0000, 0xFFFE);
+
+    //Wait DSP code version ready --- wait 1ms
+    Delayus(1000);
+
+    //Get FM DSP code version --- rd 0x83[15:8]
+    mt6628_read(0x83, &tmp);
+    tmp = (tmp >> 8);
+
+    //DSP rom code version request disable --- set 0x61 b15=0
+    mt6628_set_bits(0x61, 0x0000, 0x7FFF);
+
+    //Reset ASIP --- set 0x61[1:0] = 1
+    mt6628_set_bits(0x61, 0x0001, 0xFFFC);
+
+    WCN_DBG(FM_NTC | CHIP, "ROM version: v%d\n", (fm_s32)tmp);
+    return (fm_s32)tmp;
+}
+
+static fm_s32 mt6628_get_patch_path(fm_s32 ver, const fm_s8 **ppath)
+{
+    fm_s32 i;
+    fm_s32 max = sizeof(mt6628_patch_tbl) / sizeof(mt6628_patch_tbl[0]);
+
+    //check if the ROM version is defined or not
+    for (i = 0; i < max; i++) {
+        if ((mt6628_patch_tbl[i].idx == ver) && (fm_file_exist(mt6628_patch_tbl[i].patch) == 0)) {
+            *ppath = mt6628_patch_tbl[i].patch;
+            WCN_DBG(FM_NTC | CHIP, "Get ROM version OK\n");
+            return 0;
+        }
+    }
+
+
+    // the ROM version isn't defined, find a latest patch instead
+    for (i = max; i > 0; i--) {
+        if (fm_file_exist(mt6628_patch_tbl[i-1].patch) == 0) {
+            *ppath = mt6628_patch_tbl[i-1].patch;
+            WCN_DBG(FM_WAR | CHIP, "undefined ROM version\n");
+            return 1;
+        }
+    }
+
+    // get path failed
+    WCN_DBG(FM_ERR | CHIP, "No valid patch file\n");
+    return -FM_EPATCH;
+}
+
+
+static fm_s32 mt6628_get_coeff_path(fm_s32 ver, const fm_s8 **ppath)
+{
+    fm_s32 i;
+    fm_s32 max = sizeof(mt6628_patch_tbl) / sizeof(mt6628_patch_tbl[0]);
+
+    //check if the ROM version is defined or not
+    for (i = 0; i < max; i++) {
+        if ((mt6628_patch_tbl[i].idx == ver) && (fm_file_exist(mt6628_patch_tbl[i].coeff) == 0)) {
+            *ppath = mt6628_patch_tbl[i].coeff;
+            WCN_DBG(FM_NTC | CHIP, "Get ROM version OK\n");
+            return 0;
+        }
+    }
+
+
+    // the ROM version isn't defined, find a latest patch instead
+    for (i = max; i > 0; i--) {
+        if (fm_file_exist(mt6628_patch_tbl[i-1].coeff) == 0) {
+            *ppath = mt6628_patch_tbl[i-1].coeff;
+            WCN_DBG(FM_WAR | CHIP, "undefined ROM version\n");
+            return 1;
+        }
+    }
+
+    // get path failed
+    WCN_DBG(FM_ERR | CHIP, "No valid coeff file\n");
+    return -FM_EPATCH;
+}
+
+
+/*
+*  mt6628_DspPatch - DSP download procedure
+*  @img - source dsp bin code
+*  @len - patch length in byte
+*  @type - rom/patch/coefficient/hw_coefficient
+*/
+static fm_s32 mt6628_DspPatch(const fm_u8 *img, fm_s32 len, enum IMG_TYPE type)
+{
+    fm_u8 seg_num;
+    fm_u8 seg_id = 0;
+    fm_s32 seg_len;
+    fm_s32 ret = 0;
+    fm_u16 pkt_size;
+
+    FMR_ASSERT(img);
+
+    if (len <= 0) {
+        return -1;
+    }
+
+    seg_num = len / PATCH_SEG_LEN + 1;
+    WCN_DBG(FM_NTC | CHIP, "binary len:%d, seg num:%d\n", len, seg_num);
+
+    switch (type) {
+    case IMG_ROM:
+
+        for (seg_id = 0; seg_id < seg_num; seg_id++) {
+            seg_len = ((seg_id + 1) < seg_num) ? PATCH_SEG_LEN : (len % PATCH_SEG_LEN);
+            WCN_DBG(FM_NTC | CHIP, "rom,[seg_id:%d],  [seg_len:%d]\n", seg_id, seg_len);
+            if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK);
+            pkt_size = mt6628_rom_download(cmd_buf, TX_BUF_SIZE, seg_num, seg_id, &img[seg_id*PATCH_SEG_LEN], seg_len);
+            WCN_DBG(FM_NTC | CHIP, "pkt_size:%d\n", (fm_s32)pkt_size);
+            ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_ROM, SW_RETRY_CNT, ROM_TIMEOUT, NULL);
+            FM_UNLOCK(cmd_buf_lock);
+
+            if (ret) {
+                WCN_DBG(FM_ALT | CHIP, "mt6628_rom_download failed\n");
+                return ret;
+            }
+        }
+
+        break;
+    case IMG_PATCH:
+
+        for (seg_id = 0; seg_id < seg_num; seg_id++) {
+            seg_len = ((seg_id + 1) < seg_num) ? PATCH_SEG_LEN : (len % PATCH_SEG_LEN);
+            WCN_DBG(FM_NTC | CHIP, "patch,[seg_id:%d],  [seg_len:%d]\n", seg_id, seg_len);
+            if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK);
+            pkt_size = mt6628_patch_download(cmd_buf, TX_BUF_SIZE, seg_num, seg_id, &img[seg_id*PATCH_SEG_LEN], seg_len);
+            WCN_DBG(FM_NTC | CHIP, "pkt_size:%d\n", (fm_s32)pkt_size);
+            ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_PATCH, SW_RETRY_CNT, PATCH_TIMEOUT, NULL);
+            FM_UNLOCK(cmd_buf_lock);
+
+            if (ret) {
+                WCN_DBG(FM_ALT | CHIP, "mt6628_patch_download failed\n");
+                return ret;
+            }
+        }
+
+        break;
+    case IMG_HW_COEFFICIENT:
+
+        for (seg_id = 0; seg_id < seg_num; seg_id++) {
+            seg_len = ((seg_id + 1) < seg_num) ? PATCH_SEG_LEN : (len % PATCH_SEG_LEN);
+            WCN_DBG(FM_NTC | CHIP, "hwcoeff,[seg_id:%d],  [seg_len:%d]\n", seg_id, seg_len);
+            if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK);
+            pkt_size = mt6628_hwcoeff_download(cmd_buf, TX_BUF_SIZE, seg_num, seg_id, &img[seg_id*PATCH_SEG_LEN], seg_len);
+            WCN_DBG(FM_NTC | CHIP, "pkt_size:%d\n", (fm_s32)pkt_size);
+            ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_HWCOEFF, SW_RETRY_CNT, HWCOEFF_TIMEOUT, NULL);
+            FM_UNLOCK(cmd_buf_lock);
+
+            if (ret) {
+                WCN_DBG(FM_ALT | CHIP, "mt6628_hwcoeff_download failed\n");
+                return ret;
+            }
+        }
+
+        break;
+    case IMG_COEFFICIENT:
+
+        for (seg_id = 0; seg_id < seg_num; seg_id++) {
+            seg_len = ((seg_id + 1) < seg_num) ? PATCH_SEG_LEN : (len % PATCH_SEG_LEN);
+            WCN_DBG(FM_NTC | CHIP, "coeff,[seg_id:%d],  [seg_len:%d]\n", seg_id, seg_len);
+            if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK);
+            pkt_size = mt6628_coeff_download(cmd_buf, TX_BUF_SIZE, seg_num, seg_id, &img[seg_id*PATCH_SEG_LEN], seg_len);
+            WCN_DBG(FM_NTC | CHIP, "pkt_size:%d\n", (fm_s32)pkt_size);
+            ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_COEFF, SW_RETRY_CNT, COEFF_TIMEOUT, NULL);
+            FM_UNLOCK(cmd_buf_lock);
+
+            if (ret) {
+                WCN_DBG(FM_ALT | CHIP, "mt6628_coeff_download failed\n");
+                return ret;
+            }
+        }
+
+        break;
+    default:
+        break;
+    }
+
+    return 0;
+}
+
+
+static fm_s32 mt6628_PowerUp(fm_u16 *chip_id, fm_u16 *device_id)
+{
+#define PATCH_BUF_SIZE 4096*6
+    fm_s32 ret = 0;
+    fm_u16 pkt_size;
+    fm_u16 tmp_reg = 0;
+
+    const fm_s8 *path_patch = NULL;
+    const fm_s8 *path_coeff = NULL;
+    //const fm_s8 *path_hwcoeff = NULL;
+    //fm_s32 coeff_len = 0;
+    fm_s32 patch_len = 0;
+    fm_u8 *dsp_buf = NULL;
+
+    FMR_ASSERT(chip_id);
+    FMR_ASSERT(device_id);
+
+    WCN_DBG(FM_DBG | CHIP, "pwr on seq......\n");
+
+    //Wholechip FM Power Up: step 1, FM Digital Clock enable
+    if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK);
+    pkt_size = mt6628_pwrup_clock_on(cmd_buf, TX_BUF_SIZE);
+    ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_EN, SW_RETRY_CNT, EN_TIMEOUT, NULL);
+    FM_UNLOCK(cmd_buf_lock);
+
+    if (ret) {
+        WCN_DBG(FM_ALT | CHIP, "mt6628_pwrup_clock_on failed\n");
+        return ret;
+    }
+
+#ifdef FM_DIGITAL_INPUT
+    mt6628_I2s_Setting(MT6628_I2S_ON, MT6628_I2S_SLAVE, MT6628_I2S_44K);
+    mt_combo_audio_ctrl(COMBO_AUDIO_STATE_2);
+#endif
+
+    //Wholechip FM Power Up: step 2, read HW version
+    mt6628_read(0x62, &tmp_reg);
+    mt6628_read(0x62, &tmp_reg);
+    *chip_id = tmp_reg;
+    *device_id = tmp_reg;
+    mt6628_hw_info.chip_id = (fm_s32)tmp_reg;
+    WCN_DBG(FM_NTC | CHIP, "chip_id:0x%04x\n", tmp_reg);
+
+    if (mt6628_hw_info.chip_id != 0x6628) {
+        WCN_DBG(FM_NTC | CHIP, "fm sys error, reset hw\n");
+        return (-FM_EFW);
+    }
+    
+    mt6628_hw_info.eco_ver = (fm_s32)mtk_wcn_wmt_hwver_get();
+    WCN_DBG(FM_NTC | CHIP, "ECO version:0x%08x\n", mt6628_hw_info.eco_ver);
+    mt6628_hw_info.eco_ver += 1;
+    
+    //get mt6628 DSP rom version
+    if ((ret = mt6628_get_rom_version()) >= 0) {
+        mt6628_hw_info.rom_ver = ret;
+        WCN_DBG(FM_NTC | CHIP, "ROM version: v%d\n", mt6628_hw_info.rom_ver);
+    } else {
+        WCN_DBG(FM_ERR | CHIP, "get ROM version failed\n");
+    }
+
+
+    //Wholechip FM Power Up: step 3, download patch
+    if (!(dsp_buf = fm_vmalloc(PATCH_BUF_SIZE))) {
+        WCN_DBG(FM_ALT | CHIP, "-ENOMEM\n");
+        return -ENOMEM;
+    }
+
+    ret = mt6628_get_patch_path(mt6628_hw_info.rom_ver, &path_patch);
+    patch_len = fm_file_read(path_patch, dsp_buf, PATCH_BUF_SIZE, 0);
+    mt6628_DspPatch((const fm_u8*)dsp_buf, patch_len, IMG_PATCH);
+
+    ret = mt6628_get_coeff_path(mt6628_hw_info.rom_ver, &path_coeff);
+    patch_len = fm_file_read(path_coeff, dsp_buf, PATCH_BUF_SIZE, 0);
+
+    mt6628_hw_info.rom_ver += 1;
+    
+    tmp_reg = dsp_buf[38] | (dsp_buf[39] << 8);
+    mt6628_hw_info.patch_ver = (fm_s32)tmp_reg;
+    WCN_DBG(FM_NTC | CHIP, "Patch version: 0x%08x\n", mt6628_hw_info.patch_ver);
+    
+    if (ret == 1) {
+        dsp_buf[4] = 0x00;  //if we found rom version undefined, we should disable patch
+        dsp_buf[5] = 0x00;
+    }
+    
+    mt6628_DspPatch((const fm_u8*)dsp_buf, patch_len, IMG_COEFFICIENT);
+    mt6628_write(0x90, 0x0040);
+    mt6628_write(0x90, 0x0000);
+
+    if (dsp_buf) {
+        fm_vfree(dsp_buf);
+        dsp_buf = NULL;
+    }
+
+    //mt6628_check_dsp();
+    
+    //Wholechip FM Power Up: step 4, FM Digital Init: fm_rgf_maincon
+    if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK);
+    pkt_size = mt6628_pwrup_digital_init(cmd_buf, TX_BUF_SIZE);
+    ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_EN, SW_RETRY_CNT, EN_TIMEOUT, NULL);
+    FM_UNLOCK(cmd_buf_lock);
+    if (ret) {
+        WCN_DBG(FM_ALT | CHIP, "mt6628_pwrup_digital_init failed\n");
+        return ret;;
+    }
+
+    WCN_DBG(FM_NTC | CHIP, "pwr on seq ok\n");
+
+    //mt6628_check_dsp();
+
+//    rssi_th_set = fm_false;
+    return ret;
+}
+
+static fm_s32 mt6628_PowerDown(void)
+{
+    fm_s32 ret = 0;
+    fm_u16 pkt_size;
+    fm_u16 dataRead;
+
+    WCN_DBG(FM_DBG | CHIP, "pwr down seq\n");
+    /*SW work around for MCUFA issue.
+     *if interrupt happen before doing rampdown, DSP can't switch MCUFA back well.
+     * In case read interrupt, and clean if interrupt found before rampdown.
+     */
+    mt6628_read(FM_MAIN_INTR, &dataRead);
+
+    if (dataRead & 0x1) {
+        mt6628_write(FM_MAIN_INTR, dataRead);//clear status flag
+    }
+
+    mt6628_RampDown();
+
+#ifdef FM_DIGITAL_INPUT
+    mt6628_I2s_Setting(MT6628_I2S_OFF, MT6628_I2S_SLAVE, MT6628_I2S_44K);
+#endif
+
+    if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK);
+    pkt_size = mt6628_pwrdown(cmd_buf, TX_BUF_SIZE);
+    ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_EN, SW_RETRY_CNT, EN_TIMEOUT, NULL);
+    FM_UNLOCK(cmd_buf_lock);
+
+    if (ret) {
+        WCN_DBG(FM_ALT | CHIP, "mt6628_pwrdown failed\n");
+        return ret;
+    }
+
+    //FIX_ME, disable ext interrupt
+    mt6628_write(FM_MAIN_EXTINTRMASK, 0x00);
+
+//    rssi_th_set = fm_false;
+    return ret;
+}
+
+static fm_bool mt6628_SetFreq(fm_u16 freq)
+{
+    fm_s32 ret = 0;
+    fm_u16 pkt_size;
+    fm_u16 chan_para = 0;
+
+    fm_cb_op->cur_freq_set(freq);
+
+
+    //MCU clock adjust if need
+    if ((ret = mt6628_mcu_dese(freq, NULL)) < 0)
+       {
+               WCN_DBG(FM_ERR | MAIN, "mt6628_mcu_dese FAIL:%d\n", ret);
+    }
+
+    WCN_DBG(FM_INF | MAIN, "MCU %d\n", ret);
+
+    //GPS clock adjust if need
+    if ((ret = mt6628_gps_dese(freq, NULL)) < 0) 
+       {
+               WCN_DBG(FM_ERR | MAIN, "mt6628_gps_dese FAIL:%d\n", ret);
+    }
+
+    WCN_DBG(FM_INF | MAIN, "GPS %d\n", ret);
+    //start tune
+    if (FM_LOCK(cmd_buf_lock)) return fm_false;
+
+//    if (fm_cb_op->chan_para_get) {
+    chan_para = mt6628_chan_para_get(freq);
+        WCN_DBG(FM_DBG | CHIP, "%d chan para = %d\n", (fm_s32)freq, (fm_s32)chan_para);
+//    }
+
+    pkt_size = mt6628_tune(cmd_buf, TX_BUF_SIZE, freq, chan_para);
+    ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_TUNE | FLAG_TUNE_DONE, SW_RETRY_CNT, TUNE_TIMEOUT, NULL);
+    FM_UNLOCK(cmd_buf_lock);
+
+    if (ret) {
+        WCN_DBG(FM_ALT | CHIP, "mt6628_tune failed\n");
+        return ret;
+    }
+
+    WCN_DBG(FM_DBG | CHIP, "set freq to %d ok\n", freq);
+
+   /* if (rssi_th_set == fm_false) {
+        mt6628_set_RSSITh(MT6628fm_cust_config_fetch(FM_CFG_RX_RSSI_TH_LONG), MT6628fm_cust_config_fetch(FM_CFG_RX_RSSI_TH_SHORT));
+        mt6628_set_SMGTh(Chip_Version, MT6628fm_cust_config_fetch(FM_CFG_RX_SMG_TH));
+        rssi_th_set = fm_true;
+    }*/
+
+    return fm_true;
+}
+
+
+/*
+* mt6628_Seek
+* @pFreq - IN/OUT parm, IN start freq/OUT seek valid freq
+* @seekdir - 0:up, 1:down
+* @space - 1:50KHz, 2:100KHz, 4:200KHz
+* return fm_true:seek success; fm_false:seek failed
+*/
+static fm_bool mt6628_Seek(fm_u16 min_freq, fm_u16 max_freq, fm_u16 *pFreq, fm_u16 seekdir, fm_u16 space)
+{
+    fm_s32 ret = 0;
+    fm_u16 pkt_size,temp;
+
+    mt6628_RampDown();
+    mt6628_read(FM_MAIN_CTRL, &temp);
+    mt6628_Mute(fm_true);
+
+    if (FM_LOCK(cmd_buf_lock)) return fm_false;
+    pkt_size = mt6628_seek(cmd_buf, TX_BUF_SIZE, seekdir, space, max_freq, min_freq);
+    ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_SEEK | FLAG_SEEK_DONE, SW_RETRY_CNT, SEEK_TIMEOUT, mt6628_get_read_result);
+    FM_UNLOCK(cmd_buf_lock);
+
+    if (!ret && res) {
+        *pFreq = res->seek_result;
+        //fm_cb_op->cur_freq_set(*pFreq);
+    } else {
+        WCN_DBG(FM_ALT | CHIP, "mt6628_seek failed\n");
+        return ret;
+    }
+
+    //get the result freq
+    WCN_DBG(FM_NTC | CHIP, "seek, result freq:%d\n", *pFreq);
+    mt6628_RampDown();
+       if((temp&0x0020) == 0)
+       {
+           mt6628_Mute(fm_false);
+       }
+
+    return fm_true;
+}
+
+#define FM_CQI_LOG_PATH "/mnt/sdcard/fmcqilog"
+
+static fm_s32 mt6628_full_cqi_get(fm_s32 min_freq, fm_s32 max_freq, fm_s32 space, fm_s32 cnt)
+{
+    fm_s32 ret = 0;
+    fm_u16 pkt_size;
+    fm_u16 freq, orig_freq;
+    fm_s32 i, j, k;
+    fm_s32 space_val, max, min, num;
+    struct mt6628_full_cqi *p_cqi;
+    fm_u8 *cqi_log_title = "Freq, RSSI, PAMD, PR, FPAMD, MR, ATDC, PRX, ATDEV, SMGain, DltaRSSI\n";
+    fm_u8 cqi_log_buf[100] = {0};
+    fm_s32 pos;
+    fm_u8 cqi_log_path[100] = {0};
+    
+       WCN_DBG(FM_NTC | CHIP, "6628 cqi log start\n");
+    // for soft-mute tune, and get cqi
+    freq = fm_cb_op->cur_freq_get();
+    if (0 == fm_get_channel_space(freq)) {
+        freq *= 10;
+    }
+    // get cqi
+    orig_freq = freq;
+       if (0 == fm_get_channel_space(min_freq)) {
+               min = min_freq * 10;
+       } else {
+               min = min_freq;
+       }
+       if (0 == fm_get_channel_space(max_freq)) {
+               max = max_freq * 10;
+       } else {
+               max = max_freq;
+       }
+       if (space == 0x0001) {
+               space_val = 5; // 50Khz
+       } else if (space == 0x0002) {
+               space_val = 10; // 100Khz
+       } else if (space == 0x0004) {
+               space_val = 20; // 200Khz
+       } else {
+               space_val = 10;
+       }
+       num = (max - min) / space_val + 1; //Eg, (8760 - 8750) / 10 + 1 = 2
+    for (k = 0; (10000 == orig_freq) && (0xffffffff == g_dbg_level) && (k < cnt); k++)
+    {
+               WCN_DBG(FM_NTC | CHIP, "cqi file:%d\n", k+1);
+        freq = min;
+        pos = 0;
+        fm_memcpy(cqi_log_path, FM_CQI_LOG_PATH, strlen(FM_CQI_LOG_PATH));
+        sprintf(&cqi_log_path[strlen(FM_CQI_LOG_PATH)], "%d.txt", k+1);
+        fm_file_write(cqi_log_path, cqi_log_title, strlen(cqi_log_title), &pos);
+        for (j = 0; j < num; j++) 
+        {
+            if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK);
+            pkt_size = mt6628_full_cqi_req(cmd_buf, TX_BUF_SIZE, &freq, 1, 1);
+            ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_SM_TUNE, SW_RETRY_CNT, SM_TUNE_TIMEOUT, mt6628_get_read_result);
+            FM_UNLOCK(cmd_buf_lock);
+            
+            if (!ret && res) {
+                WCN_DBG(FM_NTC | CHIP, "smt cqi size %d\n", res->cqi[0]);
+                p_cqi = (struct mt6628_full_cqi*)&res->cqi[2];
+                for (i = 0; i < res->cqi[1]; i++) {
+                    // just for debug
+                    WCN_DBG(FM_NTC | CHIP, "freq %d, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x\n", 
+                        p_cqi[i].ch, 
+                        p_cqi[i].rssi,
+                        p_cqi[i].pamd,
+                        p_cqi[i].pr,
+                        p_cqi[i].fpamd,
+                        p_cqi[i].mr,
+                        p_cqi[i].atdc,
+                        p_cqi[i].prx,
+                        p_cqi[i].atdev,
+                        p_cqi[i].smg,
+                        p_cqi[i].drssi); 
+                    // format to buffer
+                    sprintf(cqi_log_buf, "%04d,%04x,%04x,%04x,%04x,%04x,%04x,%04x,%04x,%04x,%04x,\n", 
+                        p_cqi[i].ch, 
+                        p_cqi[i].rssi,
+                        p_cqi[i].pamd,
+                        p_cqi[i].pr,
+                        p_cqi[i].fpamd,
+                        p_cqi[i].mr,
+                        p_cqi[i].atdc,
+                        p_cqi[i].prx,
+                        p_cqi[i].atdev,
+                        p_cqi[i].smg,
+                        p_cqi[i].drssi); 
+                    // write back to log file
+                    fm_file_write(cqi_log_path, cqi_log_buf, strlen(cqi_log_buf), &pos);
+                }
+            } 
+            else 
+            {
+                WCN_DBG(FM_ALT | CHIP, "smt get CQI failed\n");
+                ret = -1;
+            }
+            freq += space_val;
+        }
+        fm_cb_op->cur_freq_set(0);//avoid run too much times
+    }
+       WCN_DBG(FM_NTC | CHIP, "6628 cqi log done\n");
+
+    return ret;
+}
+
+
+static fm_bool mt6628_Scan(fm_u16 min_freq, fm_u16 max_freq, fm_u16 *pFreq, fm_u16 *pScanTBL,
+                           fm_u16 *ScanTBLsize, fm_u16 scandir, fm_u16 space)
+{
+    fm_s32 ret = 0;
+    fm_u16 pkt_size,temp;
+    fm_u16 offset = 0;
+    fm_u16 tmp_scanTBLsize = *ScanTBLsize;
+
+    if ((!pScanTBL) || (tmp_scanTBLsize == 0)) {
+        WCN_DBG(FM_ALT | CHIP, "scan, failed:invalid scan table\n");
+        return fm_false;
+    }
+
+    WCN_DBG(FM_NTC | CHIP, "start freq: %d, max_freq:%d, min_freq:%d, scan BTL size:%d, scandir:%d, space:%d\n", *pFreq, max_freq, min_freq, *ScanTBLsize, scandir, space);
+
+    mt6628_RampDown();
+    mt6628_read(FM_MAIN_CTRL, &temp);
+    mt6628_Mute(fm_true);
+
+    mt6628_full_cqi_get(min_freq, max_freq, space, 5);
+    
+    // normal scan
+    if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK);
+    pkt_size = mt6628_scan(cmd_buf, TX_BUF_SIZE, scandir, space, max_freq, min_freq);
+    ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_SCAN | FLAG_SCAN_DONE, SW_RETRY_CNT, SCAN_TIMEOUT, mt6628_get_read_result);
+    FM_UNLOCK(cmd_buf_lock);
+
+    if (!ret && res) {
+        fm_memcpy(pScanTBL, res->scan_result, sizeof(fm_u16)*FM_SCANTBL_SIZE);
+        WCN_DBG(FM_NTC | CHIP, "Rx scan result:\n");
+
+        for (offset = 0; offset < tmp_scanTBLsize; offset++) {
+            WCN_DBG(FM_NTC | CHIP, "%d: %04x\n", (fm_s32)offset, *(pScanTBL + offset));
+        }
+
+        *ScanTBLsize = tmp_scanTBLsize;
+    } else {
+        WCN_DBG(FM_ALT | CHIP, "mt6628_scan failed\n");
+        return ret;
+    }
+
+    mt6628_set_bits(FM_MAIN_CTRL, 0x0000, 0xFFF0); //make sure tune/seek/scan/cqi bits = 0
+       if((temp&0x0020) == 0)
+       {
+               mt6628_Mute(fm_false);
+       }
+
+    return fm_true;
+}
+
+//add for scan cancel case
+static fm_bool cqi_abort = fm_false;
+
+static fm_s32 mt6628_CQI_Get(fm_s8 *buf, fm_s32 buf_len)
+{
+    fm_s32 ret = 0;
+    fm_s32 i;
+    fm_u16 pkt_size;
+    struct mt6628_fm_cqi *pmt6628_cqi;
+    struct adapt_fm_cqi  *pcqi;
+
+    if (!buf || buf_len < FM_CQI_BUF_SIZE) {
+        return -FM_EBUF;
+    }
+
+    if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK);
+    pkt_size = mt6628_cqi_get(cmd_buf, TX_BUF_SIZE);
+    if (cqi_abort == fm_true) {
+        cqi_abort = fm_false;
+        ret = -1;
+    } else {
+        ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_SCAN | FLAG_CQI_DONE, SW_RETRY_CNT, SCAN_TIMEOUT, mt6628_get_read_result);
+    }
+    FM_UNLOCK(cmd_buf_lock);
+
+    if (!ret && res) {
+        //FIXEDME
+        pmt6628_cqi = (struct mt6628_fm_cqi*)res->cqi;
+        pcqi = (struct adapt_fm_cqi*)buf;
+
+        for (i = 0; i < (sizeof(res->cqi) / sizeof(struct mt6628_fm_cqi)); i++) {
+            pcqi[i].ch = (pmt6628_cqi[i].ch * 10 / 2) + 6400;
+            pcqi[i].rssi = (fm_s32)pmt6628_cqi[i].rssi;
+
+            if (pcqi[i].rssi >= 32768) {
+                pcqi[i].rssi = pcqi[i].rssi - 65536;
+            }
+
+            pcqi[i].rssi = ((pcqi[i].rssi * 6) >> 4);
+            WCN_DBG(FM_NTC | CHIP, "%d --> %d(dbm)\n", pcqi[i].ch, pcqi[i].rssi);
+        }
+    } else {
+        WCN_DBG(FM_ALT | CHIP, "mt6628 get CQI failed:%d\n",ret);
+    }
+
+    mt6628_set_bits(FM_MAIN_CTRL, 0x0000, 0xFFF0); //make sure tune/seek/scan/cqi bits = 0
+
+    return ret;
+}
+
+static fm_bool scan_abort = fm_false;
+
+#ifdef MTK_FM_50KHZ_SUPPORT
+#define SCAN_SEG_LEN 250
+static fm_s8 raw_buf[16 * sizeof(struct adapt_fm_cqi)] = {0};
+
+static fm_bool mt6628_Scan_50KHz(fm_u16 min_freq, fm_u16 max_freq, fm_u16 *pFreq, fm_u16 *pScanTBL,
+                           fm_u16 *ScanTBLsize, fm_u16 scandir, fm_u16 space)
+{
+    fm_s32 ret = 0;
+    fm_s32 num;
+    fm_s32 seg;
+    fm_s32 i, j;
+    fm_u16 scan_tbl[FM_SCANTBL_SIZE]; //need no less than the chip
+    fm_s32 start_freq, end_freq;
+    fm_s32 ch_offset, step, tmp_val;
+    fm_s32 chl_cnt = 0;
+    fm_s32 word_offset, bit_offset;
+    fm_s32 space_val = 5;
+    struct adapt_fm_cqi *pCQI = (struct adapt_fm_cqi *)raw_buf;
+
+    if (space == 0x0001) {
+        space_val = 5; // 50Khz
+    } else if (space == 0x0002) {
+        space_val = 10; // 100Khz
+    } else if (space == 0x0004) {
+        space_val = 20; // 200Khz
+    }
+    
+    // calculate segment number
+    num = (max_freq - min_freq) / space_val; //Eg, (10800 - 8750) / 5 = 410
+    seg = (num / SCAN_SEG_LEN) + ((num % SCAN_SEG_LEN) ? 1 : 0); //Eg, (410 / 200) + ((410 % 200) ? 1 : 0) = 2 + 1 = 3
+
+    FM_FIFO_RESET(cqi_fifo);
+    fm_memset(pScanTBL, 0, sizeof(fm_u16) * (*ScanTBLsize));
+    
+    // do scan
+    scan_abort = fm_false; // reset scan cancel flag
+    for (i = 0; i < seg; i++) {
+        start_freq = min_freq + SCAN_SEG_LEN * space_val * i;
+        end_freq = min_freq + SCAN_SEG_LEN * space_val * (i + 1) - space_val;
+        end_freq = (end_freq > max_freq) ? max_freq : end_freq;
+        chl_cnt = 0;
+
+        if (fm_true == scan_abort) {
+            scan_abort = fm_false;
+            return fm_false;
+        }
+        
+        if (fm_false == mt6628_Scan(start_freq, end_freq, pFreq, scan_tbl, ScanTBLsize, scandir, space)) {
+            return fm_false;
+        }
+
+        // get channel count
+        for (ch_offset = 0; ch_offset < FM_SCANTBL_SIZE; ch_offset++) {
+                   if (scan_tbl[ch_offset] == 0)
+                           continue;
+                   for (step = 0; step < 16; step++) {
+                           if (scan_tbl[ch_offset] & (1 << step)) {
+                    tmp_val =  start_freq + (ch_offset * 16 + step) * space_val;
+                    WCN_DBG(FM_NTC | CHIP, "freq %d, end freq %d\n", tmp_val, end_freq);
+                    if (tmp_val <= end_freq) {
+                        chl_cnt++; 
+                        // set reult bitmap
+                        word_offset = (tmp_val - min_freq) / space_val / 16;
+                        bit_offset = (tmp_val - min_freq) / space_val % 16;
+                        if ((word_offset < 26) && (word_offset >= 0)) {
+                            pScanTBL[word_offset] |= (1 << bit_offset);
+                        }
+                        WCN_DBG(FM_NTC | CHIP, "cnt %d, word %d, bit %d\n", chl_cnt, word_offset, bit_offset);
+                    }
+                           }
+                   }
+           }
+
+        // get cqi info
+        while (chl_cnt > 0) {
+            ret = mt6628_CQI_Get(raw_buf, 16 * sizeof(struct adapt_fm_cqi));
+            if (ret) {
+                return ret;
+            }
+
+        // add valid channel to cqi_fifo
+        for (j = 0; j < sizeof(raw_buf) / sizeof(struct adapt_fm_cqi); j++) {
+            if ((pCQI[j].ch >= start_freq) && (pCQI[j].ch <= end_freq)) {
+                FM_FIFO_INPUT(cqi_fifo, pCQI + j);
+                WCN_DBG(FM_NTC | CHIP, "%d %d(dbm) add to fifo\n", pCQI[j].ch, pCQI[j].rssi);
+            }
+        }
+            
+            chl_cnt -= 16;
+        }
+    }
+    
+    return fm_true;
+}
+
+
+static fm_s32 mt6628_CQI_Get_50KHz(fm_s8 *buf, fm_s32 buf_len)
+{
+    fm_s32 ret = 0;
+    fm_s32 i;
+    struct adapt_fm_cqi tmp = {
+        .ch = 0,
+        .rssi = 0,
+    };
+    struct adapt_fm_cqi *pcqi = (struct adapt_fm_cqi *)buf;
+
+    
+    if (!buf || buf_len < FM_CQI_BUF_SIZE) {
+        return -FM_EBUF;
+    }
+
+    for (i = 0; ((i < (buf_len / sizeof(struct adapt_fm_cqi))) && \
+        (fm_false == FM_FIFO_IS_EMPTY(cqi_fifo))); i++) {
+        FM_FIFO_OUTPUT(cqi_fifo, &tmp);
+        pcqi[i].ch = tmp.ch;
+        pcqi[i].rssi = tmp.rssi;
+        WCN_DBG(FM_NTC | CHIP, "%d %d(dbm) get from fifo\n", pcqi[i].ch, pcqi[i].rssi);
+    }
+    
+    return ret;
+}
+
+#endif //MTK_FM_50KHZ_SUPPORT
+
+
+/*
+ * mt6628_GetCurRSSI - get current freq's RSSI value
+ * RS=RSSI
+ * If RS>511, then RSSI(dBm)= (RS-1024)/16*6
+ *                                else RSSI(dBm)= RS/16*6
+ */
+static fm_s32 mt6628_GetCurRSSI(fm_s32 *pRSSI)
+{
+    fm_u16 tmp_reg;
+
+    mt6628_read(FM_RSSI_IND, &tmp_reg);
+    tmp_reg = tmp_reg & 0x03ff;
+
+    if (pRSSI) {
+        *pRSSI = (tmp_reg > 511) ? (((tmp_reg - 1024) * 6) >> 4) : ((tmp_reg * 6) >> 4);
+        WCN_DBG(FM_DBG | CHIP, "rssi:%d, dBm:%d\n", tmp_reg, *pRSSI);
+    } else {
+        WCN_DBG(FM_ERR | CHIP, "get rssi para error\n");
+        return -FM_EPARA;
+    }
+
+    return 0;
+}
+
+static fm_u16 mt6628_vol_tbl[16] = { \
+    0x0000, 0x0519, 0x066A, 0x0814, \
+    0x0A2B, 0x0CCD, 0x101D, 0x1449, \
+    0x198A, 0x2027, 0x287A, 0x32F5, \
+    0x4027, 0x50C3, 0x65AD, 0x7FFF
+};
+static fm_s32 mt6628_SetVol(fm_u8 vol)
+{
+    fm_s32 ret = 0;
+    
+    vol = (vol > 15) ? 15 : vol;
+    ret = mt6628_write(0x7D, mt6628_vol_tbl[vol]); 
+    if (ret) {
+        WCN_DBG(FM_ERR | CHIP, "Set vol=%d Failed\n", vol);
+        return ret;
+    } else {
+        WCN_DBG(FM_DBG | CHIP, "Set vol=%d OK\n", vol);
+    }
+
+    if (vol == 10) {
+        fm_print_cmd_fifo();    //just for debug
+        fm_print_evt_fifo();
+    }
+    return 0;
+}
+
+static fm_s32 mt6628_GetVol(fm_u8 *pVol)
+{
+    int ret = 0;
+    fm_u16 tmp;
+    fm_s32 i;
+
+    FMR_ASSERT(pVol);
+
+    ret = mt6628_read(0x7D, &tmp);
+    if (ret) {
+        *pVol = 0;
+        WCN_DBG(FM_ERR | CHIP, "Get vol Failed\n");
+        return ret;
+    } 
+
+    for (i = 0; i < 16; i++) {
+        if (mt6628_vol_tbl[i] == tmp) {
+            *pVol = i;
+            break;
+        }
+    }
+
+    WCN_DBG(FM_DBG | CHIP, "Get vol=%d OK\n", *pVol);
+    return 0;
+}
+
+static fm_s32 mt6628_dump_reg(void)
+{
+       fm_s32 i;
+    fm_u16 TmpReg;
+       for(i=0; i<0xff; i++)
+       {
+        mt6628_read(i, &TmpReg);
+               WCN_DBG(FM_NTC | CHIP, "0x%02x=0x%04x\n",i,TmpReg);
+       }
+    return 0;
+}
+
+static fm_bool mt6628_GetMonoStereo(fm_u16 *pMonoStereo)
+{
+#define FM_BF_STEREO 0x1000
+    fm_u16 TmpReg;
+
+    if (pMonoStereo) {
+        mt6628_read(FM_RSSI_IND, &TmpReg);
+        *pMonoStereo = (TmpReg & FM_BF_STEREO) >> 12;
+    } else {
+        WCN_DBG(FM_ERR | CHIP, "MonoStero: para err\n");
+        return fm_false;
+    }
+
+    WCN_DBG(FM_DBG | CHIP, "MonoStero:0x%04x\n", *pMonoStereo);
+    return fm_true;
+}
+
+static fm_s32 mt6628_SetMonoStereo(fm_s32 MonoStereo)
+{
+    fm_s32 ret = 0;
+#define FM_FORCE_MS 0x0008
+
+    WCN_DBG(FM_DBG | CHIP, "set to %s\n", MonoStereo ? "mono" : "auto");
+
+    mt6628_write(0x60, 0x3007);
+
+    if (MonoStereo) {
+        ret = mt6628_set_bits(0x75, FM_FORCE_MS, ~FM_FORCE_MS);
+    } else {
+        ret = mt6628_set_bits(0x75, 0x0000, ~FM_FORCE_MS);
+    }
+
+    return ret;
+}
+
+static fm_s32 mt6628_GetCapArray(fm_s32 *ca)
+{
+    fm_u16 dataRead;
+    fm_u16 tmp = 0;
+
+    FMR_ASSERT(ca);
+    mt6628_read(0x60, &tmp);
+    mt6628_write(0x60, tmp&0xFFF7); //0x60 D3=0
+
+    mt6628_read(0x26, &dataRead);
+    *ca = dataRead;
+
+    mt6628_write(0x60, tmp); //0x60 D3=1
+    return 0;
+}
+
+/*
+ * mt6628_GetCurPamd - get current freq's PAMD value
+ * PA=PAMD
+ * If PA>511 then PAMD(dB)=  (PA-1024)/16*6,
+ *                             else PAMD(dB)=PA/16*6
+ */
+static fm_bool mt6628_GetCurPamd(fm_u16 *pPamdLevl)
+{
+    fm_u16 tmp_reg;
+    fm_u16 dBvalue,valid_cnt=0;
+       int i,total=0;
+    for (i = 0; i < 8; i++) 
+       {
+           if (mt6628_read(FM_ADDR_PAMD, &tmp_reg))
+           {
+               *pPamdLevl = 0;
+               return fm_false;
+           }
+
+           tmp_reg &= 0x03FF;
+           dBvalue = (tmp_reg > 256) ? ((512 - tmp_reg) * 6 / 16) : 0;
+               if(dBvalue != 0)
+               {
+                       total += dBvalue;
+                       valid_cnt++;
+                       WCN_DBG(FM_DBG | CHIP, "[%d]PAMD=%d\n",i,dBvalue);
+               }
+               Delayms(3);
+       }
+       if(valid_cnt != 0)
+       {
+           *pPamdLevl = total/valid_cnt;
+       }
+       else
+       {
+               *pPamdLevl = 0;
+       }
+    WCN_DBG(FM_NTC | CHIP, "PAMD=%d\n", *pPamdLevl);
+    return fm_true;
+}
+
+static fm_s32 mt6628_ScanStop(void)
+{
+    cqi_abort = fm_true;
+    scan_abort = fm_true;
+    fm_force_active_event(FLAG_SCAN_DONE | FLAG_CQI_DONE);
+    
+    return 0;
+}
+
+static fm_s32 mt6628_SeekStop(void)
+{
+    return fm_force_active_event(FLAG_SEEK_DONE);
+}
+
+
+/*
+ * mt6628_I2s_Setting - set the I2S state on MT6628
+ * @onoff - I2S on/off
+ * @mode - I2S mode: Master or Slave
+ *
+ * Return:0, if success; error code, if failed
+ */
+static fm_s32 mt6628_I2s_Setting(fm_s32 onoff, fm_s32 mode, fm_s32 sample)
+{
+    fm_u16 tmp_state = 0;
+    fm_u16 tmp_mode = 0;
+    fm_u16 tmp_sample = 0;
+    fm_s32 ret = 0;
+
+    if (onoff == MT6628_I2S_ON) {
+        tmp_state = 0x0080; //I2S Frequency tracking on, 0x61 D7=1
+        mt6628_i2s_inf.status = 1;
+    } else if (onoff == MT6628_I2S_OFF) {
+        tmp_state = 0x0000; //I2S Frequency tracking off, 0x61 D7=0
+        mt6628_i2s_inf.status = 0;
+    } else {
+        WCN_DBG(FM_ERR | CHIP, "%s():[onoff=%d]\n", __func__, onoff);
+        ret = -FM_EPARA;
+        goto out;
+    }
+
+    if (mode == MT6628_I2S_MASTER) {
+        tmp_mode = 0x0000; //6620 as I2S master, set 0x9B D3=0
+        mt6628_i2s_inf.mode = 1;
+    } else if (mode == MT6628_I2S_SLAVE) {
+        tmp_mode = 0x0008; //6620 as I2S slave, set 0x9B D3=1
+        mt6628_i2s_inf.mode = 0;
+    } else {
+        WCN_DBG(FM_ERR | CHIP, "%s():[mode=%d]\n", __func__, mode);
+        ret = -FM_EPARA;
+        goto out;
+    }
+
+    if (sample == MT6628_I2S_32K) {
+        tmp_sample = 0x0000; //6620 I2S 32KHz sample rate, 0x5F D11~12
+        mt6628_i2s_inf.rate = 32000;
+    } else if (sample == MT6628_I2S_44K) {
+        tmp_sample = 0x0800; //6620 I2S 44.1KHz sample rate
+        mt6628_i2s_inf.rate = 44100;
+    } else if (sample == MT6628_I2S_48K) {
+        tmp_sample = 0x1000; //6620 I2S 48KHz sample rate
+        mt6628_i2s_inf.rate = 48000;
+    } else {
+        WCN_DBG(FM_ERR | CHIP, "%s():[sample=%d]\n", __func__, sample);
+        ret = -FM_EPARA;
+        goto out;
+    }
+
+    if ((ret = mt6628_set_bits(0x5F, tmp_sample, 0xE7FF)))
+        goto out;
+
+    if ((ret = mt6628_set_bits(0x9B, tmp_mode, 0xFFF7)))
+        goto out;
+
+    if ((ret = mt6628_set_bits(0x61, tmp_state, 0xFF7F)))
+        goto out;
+
+    WCN_DBG(FM_NTC | CHIP, "[onoff=%s][mode=%s][sample=%d](0)33KHz,(1)44.1KHz,(2)48KHz\n",
+            (onoff == MT6628_I2S_ON) ? "On" : "Off",
+            (mode == MT6628_I2S_MASTER) ? "Master" : "Slave",
+            sample);
+out:
+    return ret;
+}
+
+
+
+static fm_s32 mt6628_i2s_info_get(fm_s32 *ponoff, fm_s32 *pmode, fm_s32 *psample)
+{
+    FMR_ASSERT(ponoff);
+    FMR_ASSERT(pmode);
+    FMR_ASSERT(psample);
+
+    *ponoff = mt6628_i2s_inf.status;
+    *pmode = mt6628_i2s_inf.mode;
+    *psample = mt6628_i2s_inf.rate;
+
+    return 0;
+}
+
+
+static fm_s32 mt6628_hw_info_get(struct fm_hw_info *req)
+{
+    FMR_ASSERT(req);
+
+    req->chip_id = mt6628_hw_info.chip_id;
+    req->eco_ver = mt6628_hw_info.eco_ver;
+    req->patch_ver = mt6628_hw_info.patch_ver;
+    req->rom_ver = mt6628_hw_info.rom_ver;
+
+    return 0;
+}
+
+static fm_s32 mt6628_soft_mute_tune(fm_u16 freq,fm_s32 *rssi,fm_bool *valid)
+{
+    fm_s32 ret=0;
+    fm_u16 pkt_size;
+    //fm_u16 freq;//, orig_freq;
+    struct mt6628_full_cqi *p_cqi;
+       fm_s32 RSSI=0, PAMD=0,MR=0, ATDC=0;
+       fm_u32 PRX=0,ATDEV=0;
+       fm_u16 softmuteGainLvl=0;
+    
+       if (FM_LOCK(cmd_buf_lock)) return (-FM_ELOCK);
+       pkt_size = mt6628_full_cqi_req(cmd_buf, TX_BUF_SIZE, &freq, 1, 1);
+       ret = fm_cmd_tx(cmd_buf, pkt_size, FLAG_SM_TUNE, SW_RETRY_CNT, SM_TUNE_TIMEOUT, mt6628_get_read_result);
+       FM_UNLOCK(cmd_buf_lock);
+       
+       if (!ret && res) 
+       {
+               WCN_DBG(FM_NTC | CHIP, "smt cqi size %d\n", res->cqi[0]);
+               p_cqi = (struct mt6628_full_cqi*)&res->cqi[2];
+               // just for debug
+               WCN_DBG(FM_NTC | CHIP, "freq %d, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x\n", 
+                       p_cqi->ch, 
+                       p_cqi->rssi,
+                       p_cqi->pamd,
+                       p_cqi->pr,
+                       p_cqi->fpamd,
+                       p_cqi->mr,
+                       p_cqi->atdc,
+                       p_cqi->prx,
+                       p_cqi->atdev,
+                       p_cqi->smg,
+                       p_cqi->drssi); 
+               RSSI = ((p_cqi->rssi & 0x03FF) >= 512) ? ((p_cqi->rssi & 0x03FF) - 1024) : (p_cqi->rssi & 0x03FF);
+               PAMD = ((p_cqi->pamd & 0x1FF) >= 256) ? ((p_cqi->pamd & 0x01FF) - 512) : (p_cqi->pamd & 0x01FF);
+               MR = ((p_cqi->mr & 0x01FF) >= 256) ? ((p_cqi->mr & 0x01FF) - 512) : (p_cqi->mr & 0x01FF);
+               ATDC =(p_cqi->atdc >= 32768) ? (65536 - p_cqi->atdc) : (p_cqi->atdc);
+               if(ATDC < 0)
+               {
+                       ATDC = (~(ATDC)) - 1;//Get abs value of ATDC
+               }
+               PRX = (p_cqi->prx & 0x00FF);
+               ATDEV = p_cqi->atdev;
+               softmuteGainLvl = p_cqi->smg;
+               //check if the channel is valid according to each CQIs
+               if((RSSI >= mt6628_fm_config.rx_cfg.long_ana_rssi_th) 
+                && (PAMD <= mt6628_fm_config.rx_cfg.pamd_th)
+                && (ATDC <= mt6628_fm_config.rx_cfg.atdc_th)
+                && (MR >= mt6628_fm_config.rx_cfg.mr_th)
+                && (PRX >= mt6628_fm_config.rx_cfg.prx_th)
+                && (ATDEV >= mt6628_fm_config.rx_cfg.atdev_th)
+                && (softmuteGainLvl >= mt6628_fm_config.rx_cfg.smg_th))
+               {        
+                       *valid = fm_true;
+               }
+               else
+               {
+                       *valid = fm_false;
+               }
+               *rssi = RSSI;
+/*             if(RSSI < -296) 
+                       WCN_DBG(FM_NTC | CHIP, "rssi\n");
+               else if(PAMD > -12) 
+                       WCN_DBG(FM_NTC | CHIP, "PAMD\n");
+               else if(ATDC > 3496) 
+                       WCN_DBG(FM_NTC | CHIP, "ATDC\n");
+               else if(MR < -67) 
+                       WCN_DBG(FM_NTC | CHIP, "MR\n");
+               else if(PRX < 80) 
+                       WCN_DBG(FM_NTC | CHIP, "PRX\n");
+               else if(ATDEV < ATDC) 
+                       WCN_DBG(FM_NTC | CHIP, "ATDEV\n");
+               else if(softmuteGainLvl < 16421) 
+                       WCN_DBG(FM_NTC | CHIP, "softmuteGainLvl\n");
+                       */
+       }
+       else 
+       {
+               WCN_DBG(FM_ALT | CHIP, "smt get CQI failed\n");
+               return fm_false;
+       }
+       WCN_DBG(FM_NTC | CHIP, "valid=%d\n",*valid);
+       return fm_true;
+}
+
+static fm_bool mt6628_em_test(fm_u16 group_idx, fm_u16 item_idx, fm_u32 item_value)
+{
+    return fm_true;
+}
+
+static fm_s32 MT6628fm_low_power_wa_default(fm_s32 fmon)
+{
+    return 0;
+}
+
+fm_s32 MT6628fm_low_ops_register(struct fm_lowlevel_ops *ops)
+{
+    fm_s32 ret = 0;
+    //Basic functions.
+
+    FMR_ASSERT(ops);
+    FMR_ASSERT(ops->cb.cur_freq_get);
+    FMR_ASSERT(ops->cb.cur_freq_set);
+    fm_cb_op = &ops->cb;
+
+    ops->bi.low_pwr_wa = MT6628fm_low_power_wa_default;
+    ops->bi.pwron = mt6628_pwron;
+    ops->bi.pwroff = mt6628_pwroff;
+    ops->bi.msdelay = Delayms;
+    ops->bi.usdelay = Delayus;
+    ops->bi.read = mt6628_read;
+    ops->bi.write = mt6628_write;
+    ops->bi.setbits = mt6628_set_bits;
+    ops->bi.chipid_get = mt6628_get_chipid;
+    ops->bi.mute = mt6628_Mute;
+    ops->bi.rampdown = mt6628_RampDown;
+    ops->bi.pwrupseq = mt6628_PowerUp;
+    ops->bi.pwrdownseq = mt6628_PowerDown;
+    ops->bi.setfreq = mt6628_SetFreq;
+    ops->bi.seek = mt6628_Seek;
+    ops->bi.seekstop = mt6628_SeekStop;
+    ops->bi.scan = mt6628_Scan;
+    ops->bi.cqi_get = mt6628_CQI_Get;
+    #ifdef MTK_FM_50KHZ_SUPPORT
+    ops->bi.scan = mt6628_Scan_50KHz;
+    ops->bi.cqi_get = mt6628_CQI_Get_50KHz;
+    #endif
+    ops->bi.scanstop = mt6628_ScanStop;
+    ops->bi.rssiget = mt6628_GetCurRSSI;
+    ops->bi.volset = mt6628_SetVol;
+    ops->bi.volget = mt6628_GetVol;
+    ops->bi.dumpreg = mt6628_dump_reg;
+    ops->bi.msget = mt6628_GetMonoStereo;
+    ops->bi.msset = mt6628_SetMonoStereo;
+    ops->bi.pamdget = mt6628_GetCurPamd;
+    ops->bi.em = mt6628_em_test;
+    ops->bi.anaswitch = mt6628_SetAntennaType;
+    ops->bi.anaget = mt6628_GetAntennaType;
+    ops->bi.caparray_get = mt6628_GetCapArray;
+    ops->bi.i2s_set = mt6628_I2s_Setting;
+    ops->bi.hwinfo_get = mt6628_hw_info_get;
+    ops->bi.i2s_get = mt6628_i2s_info_get;
+       ops->bi.is_dese_chan = mt6628_is_dese_chan;
+       ops->bi.softmute_tune = mt6628_soft_mute_tune;
+       ops->bi.desense_check = mt6628_desense_check;
+       ops->bi.cqi_log = mt6628_full_cqi_get;
+
+    cmd_buf_lock = fm_lock_create("28_cmd");
+    ret = fm_lock_get(cmd_buf_lock);
+
+    cmd_buf = fm_zalloc(TX_BUF_SIZE + 1);
+
+    if (!cmd_buf) {
+        WCN_DBG(FM_ALT | CHIP, "6628 fm lib alloc tx buf failed\n");
+        ret = -1;
+    }
+
+#ifdef MTK_FM_50KHZ_SUPPORT
+    cqi_fifo = fm_fifo_create("6628_cqi_fifo", sizeof(struct adapt_fm_cqi), 640);
+    if (!cqi_fifo) {
+        WCN_DBG(FM_ALT | CHIP, "6628 fm lib create cqi fifo failed\n");
+        ret = -1;
+    }
+#endif
+
+    return ret;
+}
+
+fm_s32 MT6628fm_low_ops_unregister(struct fm_lowlevel_ops *ops)
+{
+    fm_s32 ret = 0;
+    //Basic functions.
+    FMR_ASSERT(ops);
+
+#ifdef MTK_FM_50KHZ_SUPPORT
+    fm_fifo_release(cqi_fifo);
+#endif
+
+    if (cmd_buf) {
+        fm_free(cmd_buf);
+        cmd_buf = NULL;
+    }
+
+    ret = fm_lock_put(cmd_buf_lock);
+    fm_memset(&ops->bi, 0, sizeof(struct fm_basic_interface));
+    return ret;
+}
+//static struct fm_pub pub;
+//static struct fm_pub_cb *pub_cb = &pub.pub_tbl;
+
+static const fm_u16 mt6628_mcu_dese_list[] = {
+        7630, 7800, 7940, 8320, 9260, 9600, 9710, 9920, 10400, 10410
+};
+
+static const fm_u16 mt6628_gps_dese_list[] = {
+        7850, 7860
+};
+
+static const fm_s8 mt6628_chan_para_map[] = {
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,  //7600~7695
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  //7700~7795
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  //7800~7895
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  //7900~7995
+        8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  //8000~8095
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  //8100~8195
+        0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  //8200~8295
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  //8300~8395
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0,  //8400~8495
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  //8500~8595
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  //8600~8695
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  //8700~8795
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  //8800~8895
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  //8900~8995
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  //9000~9095
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  //9100~9195
+        0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  //9200~9295
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  //9300~9395
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0,  //9400~9495
+        1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0,  //9500~9595
+        8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  //9600~9695
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  //9700~9795
+        0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  //9800~9895
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,  //9900~9995
+        0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  //10000~10095
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  //10100~10195
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,  //10200~10295
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  //10300~10395
+        8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  //10400~10495
+        1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  //10500~10595
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  //10600~10695
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0,  //10700~10795
+        0   //10800
+};
+
+
+static const fm_u16 mt6628_scan_dese_list[] = {
+        7680, 8210, 8450, 9210, 9220, 9600, 9840, 10400, 10750, 10760
+};
+
+// return value: 0, not a de-sense channel; 1, this is a de-sense channel; else error no
+static fm_s32 mt6628_is_dese_chan(fm_u16 freq)
+{
+    fm_s32 size;
+
+    size = sizeof(mt6628_scan_dese_list) / sizeof(mt6628_scan_dese_list[0]);
+
+    if (0 == fm_get_channel_space(freq)) {
+        freq *= 10;
+    }
+    
+    while (size) {
+        if (mt6628_scan_dese_list[size -1] == freq)
+            return 1;
+
+        size--;
+    }
+
+    return 0;
+}
+
+/*  return value:
+1, is desense channel and rssi is less than threshold; 
+0, not desense channel or it is but rssi is more than threshold.*/
+static fm_s32 mt6628_desense_check(fm_u16 freq,fm_s32 rssi)
+{
+       if(mt6628_is_dese_chan(freq))
+       {
+               if(rssi<mt6628_fm_config.rx_cfg.desene_rssi_th)
+               {
+                       return 1;
+               }
+               WCN_DBG(FM_DBG | CHIP, "desen_rssi %d th:%d\n", rssi,mt6628_fm_config.rx_cfg.desene_rssi_th);
+       }
+    return 0;
+}
+
+
+// return value: 0, mcu dese disable; 1, enable; else error no
+static fm_s32 mt6628_mcu_dese(fm_u16 freq, void *arg)
+{
+    fm_mcu_desense_t state = FM_MCU_DESE_DISABLE;
+    fm_s32 len = 0;
+    fm_s32 indx = 0;
+
+    if (0 == fm_get_channel_space(freq)) {
+        freq *= 10;
+    }
+    
+    WCN_DBG(FM_DBG | CHIP, "%s, [freq=%d]\n", __func__, (int)freq);
+
+    len = sizeof(mt6628_mcu_dese_list) / sizeof(mt6628_mcu_dese_list[0]);
+    indx = 0;
+
+    while ((indx < len) && (state != FM_MCU_DESE_ENABLE)) {
+        if (mt6628_mcu_dese_list[indx] == freq) {
+            state = FM_MCU_DESE_ENABLE;
+        }
+
+        indx++;
+    }
+
+    // request 6628 MCU change clk
+    if (state == FM_MCU_DESE_DISABLE) {
+        if (!mtk_wcn_wmt_dsns_ctrl(WMTDSNS_FM_DISABLE)) {
+            return -1;
+        }
+        return 0;
+    } else {
+        if (!mtk_wcn_wmt_dsns_ctrl(WMTDSNS_FM_ENABLE)) {
+            return -1;
+        }
+        return 1;
+    }
+}
+
+
+
+// return value: 0,mcu dese disable; 1, enable; else error no
+static fm_s32 mt6628_gps_dese(fm_u16 freq, void *arg)
+{
+    fm_gps_desense_t state = FM_GPS_DESE_DISABLE;
+    fm_s32 len = 0;
+    fm_s32 indx = 0;
+
+    if (0 == fm_get_channel_space(freq)) {
+        freq *= 10;
+    }
+    
+    WCN_DBG(FM_DBG | CHIP, "%s, [freq=%d]\n", __func__, (int)freq);
+
+    len = sizeof(mt6628_gps_dese_list) / sizeof(mt6628_gps_dese_list[0]);
+    indx = 0;
+
+    while ((indx < len) && (state != FM_GPS_DESE_ENABLE)) {
+        if (mt6628_gps_dese_list[indx] == freq) {
+            state = FM_GPS_DESE_ENABLE;
+        }
+
+        indx++;
+    }
+
+    // request 6628 GPS change clk
+    if (state == FM_GPS_DESE_DISABLE) {
+        if  (!mtk_wcn_wmt_dsns_ctrl(WMTDSNS_FM_GPS_DISABLE))  {
+            return -1;
+        }
+        return 0;
+    } else {
+        if (!mtk_wcn_wmt_dsns_ctrl(WMTDSNS_FM_GPS_ENABLE)) {
+            return -1;
+        }
+        return 1;
+    }
+}
+
+
+//get channel parameter, HL side/ FA / ATJ
+static fm_u16 mt6628_chan_para_get(fm_u16 freq)
+{
+    fm_s32 pos, size;
+
+    if (0 == fm_get_channel_space(freq)) {
+        freq *= 10;
+    }
+
+    pos = (freq - 7600) / 5;
+    
+    size = sizeof(mt6628_chan_para_map) / sizeof(mt6628_chan_para_map[0]);
+
+    pos = (pos < 0) ? 0 : pos;
+    pos = (pos > (size - 1)) ? (size - 1) : pos;
+
+    return mt6628_chan_para_map[pos];
+}
+
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6628/pub/mt6628_fm_link.c b/drivers/mtk_wcn_combo/drv_fm/mt6628/pub/mt6628_fm_link.c
new file mode 100755 (executable)
index 0000000..b62c89b
--- /dev/null
@@ -0,0 +1,471 @@
+/* mt6628_fm_link.c
+ *
+ * (C) Copyright 2009
+ * MediaTek <www.MediaTek.com>
+ * Hongcheng <hongcheng.xia@MediaTek.com>
+ *
+ * MT6628 FM Radio Driver -- setup data link
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+ #if 0
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+
+#include "stp_exp.h"
+#include "wmt_exp.h"
+
+#include "fm_typedef.h"
+#include "fm_dbg.h"
+#include "fm_err.h"
+#include "fm_stdlib.h"
+
+#include "mt6628_fm.h"
+#include "mt6628_fm_link.h"
+
+static struct fm_link_event *link_event;
+
+static struct fm_trace_fifo_t *cmd_fifo;
+
+static struct fm_trace_fifo_t *evt_fifo;
+    
+static fm_s32 (*reset)(fm_s32 sta) = NULL;
+
+static void mt6628_fm_wholechip_rst_cb(ENUM_WMTDRV_TYPE_T src,
+                                ENUM_WMTDRV_TYPE_T dst,
+                                ENUM_WMTMSG_TYPE_T type,
+                                void *buf,
+                                unsigned int sz)
+{
+    //To handle reset procedure please
+    ENUM_WMTRSTMSG_TYPE_T rst_msg;
+    
+    if (sz <= sizeof(ENUM_WMTRSTMSG_TYPE_T)) {
+        memcpy((char *)&rst_msg, (char *)buf, sz);
+        WCN_DBG(FM_WAR | LINK, "[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_FM) && (type == WMTMSG_TYPE_RESET)) {
+            if (rst_msg == WMTRSTMSG_RESET_START) {
+                WCN_DBG(FM_WAR | LINK, "FM restart start!\n");
+                if (reset) {
+                    reset(1);
+                }
+                
+            } else if (rst_msg == WMTRSTMSG_RESET_END) {
+                WCN_DBG(FM_WAR | LINK, "FM restart end!\n");
+                if (reset) {
+                    reset(0);
+                }
+            }
+        }
+    } else {
+        /*message format invalid*/
+        WCN_DBG(FM_WAR | LINK, "message format invalid!\n");
+    }
+}
+
+    
+fm_s32 fm_link_setup(void* data)
+{
+    fm_s32 ret = 0;
+    
+    if (!(link_event = fm_zalloc(sizeof(struct fm_link_event)))) {
+        WCN_DBG(FM_ALT | LINK, "fm_zalloc(fm_link_event) -ENOMEM\n");
+        return -1;
+    }
+
+    link_event->ln_event = fm_flag_event_create("ln_evt");
+
+    if (!link_event->ln_event) {
+        WCN_DBG(FM_ALT | LINK, "create mt6628_ln_event failed\n");
+        fm_free(link_event);
+        return -1;
+    }
+
+    fm_flag_event_get(link_event->ln_event);
+
+
+    WCN_DBG(FM_NTC | LINK, "fm link setup\n");
+
+    cmd_fifo = fm_trace_fifo_create("cmd_fifo");
+    if (!cmd_fifo) {
+        WCN_DBG(FM_ALT | LINK, "create cmd_fifo failed\n");
+        ret = -1;
+        goto failed;
+    }
+    
+    evt_fifo = fm_trace_fifo_create("evt_fifo");
+    if (!evt_fifo) {
+        WCN_DBG(FM_ALT | LINK, "create evt_fifo failed\n");
+        ret = -1;
+        goto failed;
+    }
+    
+    reset = data; // get whole chip reset cb
+    mtk_wcn_wmt_msgcb_reg(WMTDRV_TYPE_FM, mt6628_fm_wholechip_rst_cb);
+    return 0;
+    
+failed:
+    fm_trace_fifo_release(evt_fifo);
+    fm_trace_fifo_release(cmd_fifo);
+    fm_flag_event_put(link_event->ln_event);
+    if (link_event) {
+        fm_free(link_event);
+    }
+    
+    return ret;
+}
+
+fm_s32 fm_link_release(void)
+{
+
+    fm_trace_fifo_release(evt_fifo);
+    fm_trace_fifo_release(cmd_fifo);
+    fm_flag_event_put(link_event->ln_event);
+    if (link_event) {
+        fm_free(link_event);
+    }
+
+    WCN_DBG(FM_NTC | LINK, "fm link release\n");
+    return 0;
+}
+
+/*
+ * fm_ctrl_rx
+ * the low level func to read a rigister
+ * @addr - rigister address
+ * @val - the pointer of target buf
+ * If success, return 0; else error code
+ */
+fm_s32 fm_ctrl_rx(fm_u8 addr, fm_u16 *val)
+{
+    return 0;
+}
+
+/*
+ * fm_ctrl_tx
+ * the low level func to write a rigister
+ * @addr - rigister address
+ * @val - value will be writed in the rigister
+ * If success, return 0; else error code
+ */
+fm_s32 fm_ctrl_tx(fm_u8 addr, fm_u16 val)
+{
+    return 0;
+}
+
+/*
+ * fm_cmd_tx() - send cmd to FM firmware and wait event
+ * @buf - send buffer
+ * @len - the length of cmd
+ * @mask - the event flag mask
+ * @   cnt - the retry conter
+ * @timeout - timeout per cmd
+ * Return 0, if success; error code, if failed
+ */
+fm_s32 fm_cmd_tx(fm_u8* buf, fm_u16 len, fm_s32 mask, fm_s32 cnt, fm_s32 timeout, fm_s32(*callback)(struct fm_res_ctx* result))
+{
+    fm_s32 ret_time = 0;
+    struct task_struct *task = current;
+    struct fm_trace_t trace;
+
+    if ((NULL == buf) || (len < 0) || (0 == mask)
+            || (cnt > SW_RETRY_CNT_MAX) || (timeout > SW_WAIT_TIMEOUT_MAX)) {
+        WCN_DBG(FM_ERR | LINK, "cmd tx, invalid para\n");
+        return -FM_EPARA;
+    }
+
+    FM_EVENT_CLR(link_event->ln_event, mask);
+    
+#ifdef FM_TRACE_ENABLE
+    trace.type = buf[0];
+    trace.opcode = buf[1];
+    trace.len = len - 4;
+    trace.tid = (fm_s32)task->pid;
+    fm_memset(trace.pkt, 0, FM_TRACE_PKT_SIZE);
+    fm_memcpy(trace.pkt, &buf[4], (trace.len > FM_TRACE_PKT_SIZE) ? FM_TRACE_PKT_SIZE : trace.len);
+#endif
+
+sw_retry:
+
+#ifdef FM_TRACE_ENABLE
+    if (fm_true == FM_TRACE_FULL(cmd_fifo)) {
+        FM_TRACE_OUT(cmd_fifo, NULL);
+    }
+    FM_TRACE_IN(cmd_fifo, &trace);
+#endif
+
+    //send cmd to FM firmware
+    if (mtk_wcn_stp_send_data(buf, len, FM_TASK_INDX) == 0) {
+        WCN_DBG(FM_EMG | LINK, "send data over stp failed\n");
+        return -FM_ELINK;
+    }
+
+    //wait the response form FM firmware
+    ret_time = FM_EVENT_WAIT_TIMEOUT(link_event->ln_event, mask, timeout);
+
+    if (!ret_time) {
+        if (0 < cnt--) {
+            WCN_DBG(FM_WAR | LINK, "wait even timeout, [retry_cnt=%d], pid=%d\n", cnt, task->pid);
+            fm_print_cmd_fifo();
+            fm_print_evt_fifo();
+            return -FM_EFW;
+            goto sw_retry; //retry if timeout and retry cnt > 0
+        } else {
+            WCN_DBG(FM_ALT | LINK, "fatal error, SW retry failed, reset HW\n");
+            return -FM_EFW;
+        }
+    }
+
+    FM_EVENT_CLR(link_event->ln_event, mask);
+
+    if (callback) {
+        callback(&link_event->result);
+    }
+
+    return 0;
+}
+
+fm_s32 fm_event_parser(fm_s32(*rds_parser)(struct rds_rx_t*, fm_s32))
+{
+    fm_s32 len;
+    fm_s32 i = 0;
+    fm_u8 opcode = 0;
+    fm_u16 length = 0;
+    fm_u8 ch;
+    fm_u8 rx_buf[RX_BUF_SIZE + 10] = {0}; //the 10 bytes are protect gaps
+    static volatile fm_task_parser_state state = FM_TASK_RX_PARSER_PKT_TYPE;
+    struct fm_trace_t trace;
+    struct task_struct *task = current;
+
+    len = mtk_wcn_stp_receive_data(rx_buf, RX_BUF_SIZE, FM_TASK_INDX);
+    WCN_DBG(FM_DBG | LINK, "[len=%d],[CMD=0x%02x 0x%02x 0x%02x 0x%02x]\n", len, rx_buf[0], rx_buf[1], rx_buf[2], rx_buf[3]);
+
+    while (i < len) {
+        ch = rx_buf[i];
+
+        switch (state) {
+        case FM_TASK_RX_PARSER_PKT_TYPE:
+
+            if (ch == FM_TASK_EVENT_PKT_TYPE) {
+                if ((i + 5) < RX_BUF_SIZE) {
+                    WCN_DBG(FM_DBG | LINK, "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x \n", rx_buf[i], rx_buf[i+1], rx_buf[i+2], rx_buf[i+3], rx_buf[i+4], rx_buf[i+5]);
+                } else {
+                    WCN_DBG(FM_DBG | LINK, "0x%02x 0x%02x\n", rx_buf[i], rx_buf[i+1]);
+                }
+
+                state = FM_TASK_RX_PARSER_OPCODE;
+            } else {
+                WCN_DBG(FM_ALT | LINK, "event pkt type error (rx_buf[%d] = 0x%02x)\n", i, ch);
+            }
+
+            i++;
+            break;
+
+        case FM_TASK_RX_PARSER_OPCODE:
+            i++;
+            opcode = ch;
+            state = FM_TASK_RX_PARSER_PKT_LEN_1;
+            break;
+
+        case FM_TASK_RX_PARSER_PKT_LEN_1:
+            i++;
+            length = ch;
+            state = FM_TASK_RX_PARSER_PKT_LEN_2;
+            break;
+
+        case FM_TASK_RX_PARSER_PKT_LEN_2:
+            i++;
+            length |= (fm_u16)(ch << 0x8);
+
+#ifdef FM_TRACE_ENABLE
+            trace.type = FM_TASK_EVENT_PKT_TYPE;
+            trace.opcode = opcode;
+            trace.len = length;
+            trace.tid = (fm_s32)task->pid;
+            fm_memset(trace.pkt, 0, FM_TRACE_PKT_SIZE);
+            fm_memcpy(trace.pkt, &rx_buf[i], (length > FM_TRACE_PKT_SIZE) ? FM_TRACE_PKT_SIZE : length);
+
+            if (fm_true == FM_TRACE_FULL(cmd_fifo)) {
+                FM_TRACE_OUT(cmd_fifo, NULL);
+            }
+            FM_TRACE_IN(cmd_fifo, &trace);
+#endif
+            if (length > 0) {
+                state = FM_TASK_RX_PARSER_PKT_PAYLOAD;
+            } else {
+                state = FM_TASK_RX_PARSER_PKT_TYPE;
+                FM_EVENT_SEND(link_event->ln_event, (1 << opcode));
+            }
+
+            break;
+
+        case FM_TASK_RX_PARSER_PKT_PAYLOAD:
+
+            switch (opcode) {
+            case FM_TUNE_OPCODE:
+
+                if ((length == 1) && (rx_buf[i] == 1)) {
+                    FM_EVENT_SEND(link_event->ln_event, FLAG_TUNE_DONE);
+                }
+
+                break;
+
+            case FM_SOFT_MUTE_TUNE_OPCODE:
+
+                if (length >= 2) {
+                    fm_memcpy(link_event->result.cqi, &rx_buf[i], (length > FM_CQI_BUF_SIZE) ? FM_CQI_BUF_SIZE : length);
+                    FM_EVENT_SEND(link_event->ln_event, FLAG_SM_TUNE);
+                }
+                break;
+                
+            case FM_SEEK_OPCODE:
+
+                if ((i + 1) < RX_BUF_SIZE) {
+                    link_event->result.seek_result = rx_buf[i] + (rx_buf[i+1] << 8); // 8760 means 87.60Mhz
+                }
+
+                FM_EVENT_SEND(link_event->ln_event, FLAG_SEEK_DONE);
+                break;
+
+            case FM_SCAN_OPCODE:
+
+                //check if the result data is long enough
+                if ((RX_BUF_SIZE - i) < (sizeof(fm_u16) * FM_SCANTBL_SIZE)) {
+                    WCN_DBG(FM_ALT | LINK, "FM_SCAN_OPCODE err, [tblsize=%d],[bufsize=%d]\n", (sizeof(fm_u16) * FM_SCANTBL_SIZE), (RX_BUF_SIZE - i));
+                    FM_EVENT_SEND(link_event->ln_event, FLAG_SCAN_DONE);
+                    return 0;
+                } else if ((length >= FM_CQI_BUF_SIZE) && ((RX_BUF_SIZE - i) >= FM_CQI_BUF_SIZE)) {
+                    fm_memcpy(link_event->result.cqi, &rx_buf[i], FM_CQI_BUF_SIZE);
+                    FM_EVENT_SEND(link_event->ln_event, FLAG_CQI_DONE);
+                } else {
+                    fm_memcpy(link_event->result.scan_result, &rx_buf[i], sizeof(fm_u16) * FM_SCANTBL_SIZE);
+                    FM_EVENT_SEND(link_event->ln_event, FLAG_SCAN_DONE);
+                }
+
+                break;
+
+            case FSPI_READ_OPCODE:
+
+                if ((i + 1) < RX_BUF_SIZE) {
+                    link_event->result.fspi_rd = (rx_buf[i] + (rx_buf[i+1] << 8));
+                }
+
+                FM_EVENT_SEND(link_event->ln_event, (1 << opcode));
+                break;
+
+            case RDS_RX_DATA_OPCODE:
+
+                //check if the rds data is long enough
+                if ((RX_BUF_SIZE - i) < length) {
+                    WCN_DBG(FM_ALT | LINK, "RDS RX err, [rxlen=%d],[bufsize=%d]\n", (fm_s32)length, (RX_BUF_SIZE - i));
+                    FM_EVENT_SEND(link_event->ln_event, (1 << opcode));
+                    break;
+                }
+
+                //copy rds data to rds buf
+                fm_memcpy(&link_event->result.rds_rx_result, &rx_buf[i], length);
+
+                /*Handle the RDS data that we get*/
+                if (rds_parser) {
+                    rds_parser(&link_event->result.rds_rx_result, length);
+                } else {
+                    WCN_DBG(FM_WAR | LINK, "no method to parse RDS data\n");
+                }
+
+                FM_EVENT_SEND(link_event->ln_event, (1 << opcode));
+                break;
+
+            default:
+                FM_EVENT_SEND(link_event->ln_event, (1 << opcode));
+                break;
+            }
+
+            state = FM_TASK_RX_PARSER_PKT_TYPE;
+            i += length;
+            break;
+
+        default:
+            break;
+        }
+    }
+
+    return 0;
+}
+
+fm_bool fm_wait_stc_done(fm_u32 sec)
+{
+    return fm_true;
+}
+
+fm_s32 fm_force_active_event(fm_u32 mask)
+{
+    fm_u32 flag;
+
+    flag = FM_EVENT_GET(link_event->ln_event);
+    WCN_DBG(FM_WAR | LINK, "before force active event, [flag=0x%08x]\n", flag);
+    flag = FM_EVENT_SEND(link_event->ln_event, mask);
+    WCN_DBG(FM_WAR | LINK, "after force active event, [flag=0x%08x]\n", flag);
+
+    return 0;
+}
+
+
+extern fm_s32 fm_print_cmd_fifo(void)
+{
+#ifdef FM_TRACE_ENABLE
+    struct fm_trace_t trace;
+    fm_s32 i = 0;
+    
+    while (fm_false == FM_TRACE_EMPTY(cmd_fifo)) {
+        fm_memset(trace.pkt, 0, FM_TRACE_PKT_SIZE);
+        FM_TRACE_OUT(cmd_fifo, &trace);
+        WCN_DBG(FM_ALT | LINK, "trace, type %d, op %d, len %d, tid %d, time %d\n", trace.type, trace.opcode, trace.len, trace.tid, jiffies_to_msecs(abs(trace.time)));
+        i = 0;
+        while ((trace.len > 0) && (i < trace.len) && (i < (FM_TRACE_PKT_SIZE-8))) {
+            WCN_DBG(FM_ALT | LINK, "trace, %02x %02x %02x %02x %02x %02x %02x %02x\n", \
+                trace.pkt[i], trace.pkt[i+1], trace.pkt[i+2], trace.pkt[i+3], trace.pkt[i+4], trace.pkt[i+5], trace.pkt[i+6], trace.pkt[i+7]);
+            i += 8;
+        }
+        WCN_DBG(FM_ALT | LINK, "trace\n");
+    }
+#endif
+
+    return 0;
+}
+
+extern fm_s32 fm_print_evt_fifo(void)
+{
+#ifdef FM_TRACE_ENABLE
+    struct fm_trace_t trace;
+    fm_s32 i = 0;
+    
+    while (fm_false == FM_TRACE_EMPTY(evt_fifo)) {
+        fm_memset(trace.pkt, 0, FM_TRACE_PKT_SIZE);
+        FM_TRACE_OUT(evt_fifo, &trace);
+        WCN_DBG(FM_ALT | LINK, "%s: op %d, len %d, %d\n", evt_fifo->name, trace.opcode, trace.len, jiffies_to_msecs(abs(trace.time)));
+        i = 0;
+        while ((trace.len > 0) && (i < trace.len) && (i < (FM_TRACE_PKT_SIZE-8))) {
+            WCN_DBG(FM_ALT | LINK, "%s: %02x %02x %02x %02x %02x %02x %02x %02x\n", \
+                evt_fifo->name, trace.pkt[i], trace.pkt[i+1], trace.pkt[i+2], trace.pkt[i+3], trace.pkt[i+4], trace.pkt[i+5], trace.pkt[i+6], trace.pkt[i+7]);
+            i += 8;
+        }
+        WCN_DBG(FM_ALT | LINK, "%s\n", evt_fifo->name);
+    }
+#endif
+
+    return 0;
+}
+#endif
diff --git a/drivers/mtk_wcn_combo/drv_fm/mt6628/pub/mt6628_fm_rds.c b/drivers/mtk_wcn_combo/drv_fm/mt6628/pub/mt6628_fm_rds.c
new file mode 100755 (executable)
index 0000000..c16eabe
--- /dev/null
@@ -0,0 +1,315 @@
+/* mt6628_rds.c
+ *
+ * (C) Copyright 2009
+ * MediaTek <www.MediaTek.com>
+ * hongcheng <hongcheng.xia@MediaTek.com>
+ *
+ * mt6628 FM Radio Driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include "fm_typedef.h"
+#include "fm_dbg.h"
+#include "fm_err.h"
+#include "fm_interface.h"
+#include "fm_stdlib.h"
+#include "fm_rds.h"
+#include "mt6628_fm_reg.h"
+
+
+static fm_bool bRDS_FirstIn = fm_false;
+static fm_u32 gBLER_CHK_INTERVAL = 5000;
+static fm_u16 GOOD_BLK_CNT = 0, BAD_BLK_CNT = 0;
+static fm_u8 BAD_BLK_RATIO = 0;
+
+static struct fm_callback *fm_cb = NULL;
+static struct fm_basic_interface *fm_bi = NULL;
+
+
+static fm_bool mt6628_RDS_support(void);
+static fm_s32 mt6628_RDS_enable(void);
+static fm_s32 mt6628_RDS_disable(void);
+static fm_u16 mt6628_RDS_Get_GoodBlock_Counter(void);
+static fm_u16 mt6628_RDS_Get_BadBlock_Counter(void);
+static fm_u8 mt6628_RDS_Get_BadBlock_Ratio(void);
+static fm_u32 mt6628_RDS_Get_BlerCheck_Interval(void);
+// static void mt6628_RDS_GetData(fm_u16 *data, fm_u16 datalen);
+static void mt6628_RDS_Init_Data(rds_t *pstRDSData);
+
+
+
+static fm_bool mt6628_RDS_support(void)
+{
+    return fm_true;
+}
+
+static fm_s32 mt6628_RDS_enable(void)
+{
+    fm_s32 ret = 0;
+    fm_u16 dataRead;
+
+    WCN_DBG(FM_DBG | RDSC, "rds enable\n");
+    ret = fm_bi->read(FM_RDS_CFG0, &dataRead);
+    ret = fm_bi->write(FM_RDS_CFG0, 6); //set buf_start_th
+    ret = fm_bi->read(FM_MAIN_CTRL, &dataRead);
+    ret = fm_bi->write(FM_MAIN_CTRL, dataRead | (RDS_MASK));
+
+    return ret;
+}
+
+static fm_s32 mt6628_RDS_disable(void)
+{
+    fm_s32 ret = 0;
+    fm_u16 dataRead;
+
+    WCN_DBG(FM_DBG | RDSC, "rds disable\n");
+    ret = fm_bi->read(FM_MAIN_CTRL, &dataRead);
+    ret = fm_bi->write(FM_MAIN_CTRL, dataRead&(~RDS_MASK));
+
+    return ret;
+}
+
+static fm_u16 mt6628_RDS_Get_GoodBlock_Counter(void)
+{
+    fm_u16 tmp_reg;
+
+    fm_bi->read(FM_RDS_GOODBK_CNT, &tmp_reg);
+    GOOD_BLK_CNT = tmp_reg;
+    WCN_DBG(FM_DBG | RDSC, "get good block cnt:%d\n", (fm_s32)tmp_reg);
+
+    return tmp_reg;
+}
+
+static fm_u16 mt6628_RDS_Get_BadBlock_Counter(void)
+{
+    fm_u16 tmp_reg;
+
+    fm_bi->read(FM_RDS_BADBK_CNT, &tmp_reg);
+    BAD_BLK_CNT = tmp_reg;
+    WCN_DBG(FM_DBG | RDSC, "get bad block cnt:%d\n", (fm_s32)tmp_reg);
+
+    return tmp_reg;
+}
+
+static fm_u8 mt6628_RDS_Get_BadBlock_Ratio(void)
+{
+    fm_u16 tmp_reg;
+    fm_u16 gbc;
+    fm_u16 bbc;
+
+    gbc = mt6628_RDS_Get_GoodBlock_Counter();
+    bbc = mt6628_RDS_Get_BadBlock_Counter();
+
+    if ((gbc + bbc) > 0) {
+        tmp_reg = (fm_u8)(bbc * 100 / (gbc + bbc));
+    } else {
+        tmp_reg = 0;
+    }
+
+    BAD_BLK_RATIO = tmp_reg;
+    WCN_DBG(FM_DBG | RDSC, "get badblock ratio:%d\n", (fm_s32)tmp_reg);
+
+    return tmp_reg;
+}
+
+static fm_s32 mt6628_RDS_BlockCounter_Reset(void)
+{
+    mt6628_RDS_disable();
+    mt6628_RDS_enable();
+
+    return 0;
+}
+
+static fm_u32 mt6628_RDS_Get_BlerCheck_Interval(void)
+{
+    return gBLER_CHK_INTERVAL;
+}
+
+static fm_s32 mt6628_RDS_BlerCheck(rds_t *dst)
+{
+    return 0;
+}
+
+#if 0
+static void RDS_Recovery_Handler(void)
+{
+    fm_u16 tempData = 0;
+
+    do {
+        fm_bi->read(FM_RDS_DATA_REG, &tempData);
+        fm_bi->read(FM_RDS_POINTER, &tempData);
+    } while (tempData & 0x3);
+}
+#endif
+
+#if 0
+static void mt6628_RDS_GetData(fm_u16 *data, fm_u16 datalen)
+{
+#define RDS_GROUP_DIFF_OFS          0x007C
+#define RDS_FIFO_DIFF               0x007F
+#define RDS_CRC_BLK_ADJ             0x0020
+#define RDS_CRC_CORR_CNT            0x001E
+#define RDS_CRC_INFO                0x0001
+
+    fm_u16 CRC = 0, i = 0, RDS_adj = 0, RDSDataCount = 0, FM_WARorrCnt = 0;
+    fm_u16 temp = 0, OutputPofm_s32 = 0;
+
+    WCN_DBG(FM_DBG | RDSC, "get data\n");
+    fm_bi->read(FM_RDS_FIFO_STATUS0, &temp);
+    RDSDataCount = ((RDS_GROUP_DIFF_OFS & temp) << 2);
+
+    if ((temp & RDS_FIFO_DIFF) >= 4) {
+        //block A data and info handling
+        fm_bi->read(FM_RDS_INFO, &temp);
+        RDS_adj |= (temp & RDS_CRC_BLK_ADJ) << 10;
+        CRC |= (temp & RDS_CRC_INFO) << 3;
+        FM_WARorrCnt |= ((temp & RDS_CRC_CORR_CNT) << 11);
+        fm_bi->read(FM_RDS_DATA_REG, &data[0]);
+
+        //block B data and info handling
+        fm_bi->read(FM_RDS_INFO, &temp);
+        RDS_adj |= (temp & RDS_CRC_BLK_ADJ) << 9;
+        CRC |= (temp & RDS_CRC_INFO) << 2;
+        FM_WARorrCnt |= ((temp & RDS_CRC_CORR_CNT) << 7);
+        fm_bi->read(FM_RDS_DATA_REG, &data[1]);
+
+        //block C data and info handling
+        fm_bi->read(FM_RDS_INFO, &temp);
+        RDS_adj |= (temp & RDS_CRC_BLK_ADJ) << 8;
+        CRC |= (temp & RDS_CRC_INFO) << 1;
+        FM_WARorrCnt |= ((temp & RDS_CRC_CORR_CNT) << 3);
+        fm_bi->read(FM_RDS_DATA_REG, &data[2]);
+
+        //block D data and info handling
+        fm_bi->read(FM_RDS_INFO, &temp);
+        RDS_adj |= (temp & RDS_CRC_BLK_ADJ) << 7;
+        CRC |= (temp & RDS_CRC_INFO);
+        FM_WARorrCnt |= ((temp & RDS_CRC_CORR_CNT) >> 1);
+        fm_bi->read(FM_RDS_DATA_REG, &data[3]);
+
+        data[4] = (CRC | RDS_adj | RDSDataCount);
+        data[5] = FM_WARorrCnt;
+
+        fm_bi->read(FM_RDS_PWDI, &data[6]);
+        fm_bi->read(FM_RDS_PWDQ, &data[7]);
+
+        fm_bi->read(FM_RDS_POINTER, &OutputPofm_s32);
+
+        //Go fm_s32o RDS recovery handler while RDS output pofm_s32 doesn't align to 4 in numeric
+        if (OutputPofm_s32 & 0x3) {
+            RDS_Recovery_Handler();
+        }
+
+    } else {
+        for (; i < 8; i++)
+            data[i] = 0;
+    }
+}
+#endif
+
+static void mt6628_RDS_Init_Data(rds_t *pstRDSData)
+{
+    fm_memset(pstRDSData, 0 , sizeof(rds_t));
+    bRDS_FirstIn = fm_true;
+
+    fm_memset(pstRDSData->RT_Data.TextData, 0x20, sizeof(pstRDSData->RT_Data.TextData));
+    fm_memset(pstRDSData->PS_Data.PS, '\0', sizeof(pstRDSData->PS_Data.PS));
+    fm_memset(pstRDSData->PS_ON, 0x20, sizeof(pstRDSData->PS_ON));
+}
+
+fm_bool mt6628_RDS_OnOff(rds_t *dst, fm_bool bFlag)
+{
+    if (mt6628_RDS_support() == fm_false) {
+        WCN_DBG(FM_ALT | RDSC, "mt6628_RDS_OnOff failed, RDS not support\n");
+        return fm_false;
+    }
+
+    if (bFlag) {
+        mt6628_RDS_Init_Data(dst);
+        mt6628_RDS_enable();
+    } else {
+        mt6628_RDS_disable();
+    }
+
+    return fm_true;
+}
+
+DEFINE_RDSLOG(mt6628_rds_log);
+
+/* mt6628_RDS_Efm_s32_Handler    -    response FM RDS interrupt
+ * @fm - main data structure of FM driver
+ * This function first get RDS raw data, then call RDS spec parser
+ */
+static fm_s32 mt6628_rds_parser(rds_t *rds_dst, struct rds_rx_t *rds_raw, fm_s32 rds_size, fm_u16(*getfreq)(void))
+{
+    mt6628_rds_log.log_in(&mt6628_rds_log, rds_raw, rds_size);
+    return rds_parser(rds_dst, rds_raw, rds_size, getfreq);
+}
+
+static fm_s32 mt6628_rds_log_get(struct rds_rx_t *dst, fm_s32 *dst_len)
+{
+    return mt6628_rds_log.log_out(&mt6628_rds_log, dst, dst_len);
+}
+
+static fm_s32 mt6628_rds_gc_get(struct rds_group_cnt_t *dst, rds_t *rdsp)
+{
+    return rds_grp_counter_get(dst, &rdsp->gc);
+}
+
+static fm_s32 mt6628_rds_gc_reset(rds_t *rdsp)
+{
+    return rds_grp_counter_reset(&rdsp->gc);
+}
+
+fm_s32 MT6628fm_rds_ops_register(struct fm_lowlevel_ops *ops)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(ops);
+    FMR_ASSERT(ops->bi.write);
+    FMR_ASSERT(ops->bi.read);
+    FMR_ASSERT(ops->bi.setbits);
+    FMR_ASSERT(ops->bi.usdelay);
+    fm_bi = &ops->bi;
+
+    FMR_ASSERT(ops->cb.cur_freq_get);
+    FMR_ASSERT(ops->cb.cur_freq_set);
+    fm_cb = &ops->cb;
+
+    ops->ri.rds_blercheck = mt6628_RDS_BlerCheck;
+    ops->ri.rds_onoff = mt6628_RDS_OnOff;
+    ops->ri.rds_parser = mt6628_rds_parser;
+    ops->ri.rds_gbc_get = mt6628_RDS_Get_GoodBlock_Counter;
+    ops->ri.rds_bbc_get = mt6628_RDS_Get_BadBlock_Counter;
+    ops->ri.rds_bbr_get = mt6628_RDS_Get_BadBlock_Ratio;
+    ops->ri.rds_bc_reset = mt6628_RDS_BlockCounter_Reset;
+    ops->ri.rds_bci_get = mt6628_RDS_Get_BlerCheck_Interval;
+    ops->ri.rds_log_get = mt6628_rds_log_get;
+    ops->ri.rds_gc_get = mt6628_rds_gc_get;
+    ops->ri.rds_gc_reset = mt6628_rds_gc_reset;
+    return ret;
+}
+
+fm_s32 MT6628fm_rds_ops_unregister(struct fm_lowlevel_ops *ops)
+{
+    fm_s32 ret = 0;
+
+    FMR_ASSERT(ops);
+
+    fm_bi = NULL;
+    fm_memset(&ops->ri, 0, sizeof(struct fm_rds_interface));
+    return ret;
+}
+
diff --git a/drivers/mtk_wcn_combo/drv_fm/private/Makefile b/drivers/mtk_wcn_combo/drv_fm/private/Makefile
new file mode 100755 (executable)
index 0000000..1a8e796
--- /dev/null
@@ -0,0 +1,44 @@
+# Makefile generated by Mediatek
+
+# fm support
+ifeq ($(MTK_FM_SUPPORT), yes)
+
+ifeq ($(CUSTOM_KERNEL_FM), mt6628)
+PRIV_CHIP = mt6628
+PRIV_SRC_PATH = private/src/$(PRIV_CHIP)
+PRIV_CONFIG = $(CONFIG_MTK_FM)
+
+ccflags-y :=  \
+                               -I$(src)/inc \
+                               -I$(src)/$(PRIV_SRC_PATH) \
+                               -I$(src)/../inc \
+                               -I$(src)/../cust/$(PRIV_CHIP) \
+                               -I$(src)/../../combo/common_mt6628/include \
+                               -I$(src)/../../combo/common_mt6628/linux/include 
+
+
+obj-$(PRIV_CONFIG) += mtk_fm_priv.o
+mtk_fm_priv-objs       := \
+                               src/$(PRIV_CHIP)/$(PRIV_CHIP)_fm_private.o 
+endif
+
+ifeq ($(CUSTOM_KERNEL_FM), mt6620)
+PRIV_CHIP = mt6620
+PRIV_SRC_PATH = private/src/$(PRIV_CHIP)
+PRIV_CONFIG = $(CONFIG_MTK_FM)
+
+ccflags-y :=  \
+                               -I$(src)/inc \
+                               -I$(src)/$(PRIV_SRC_PATH) \
+                               -I$(src)/../inc \
+                               -I$(src)/../cust/$(PRIV_CHIP) \
+                               -I$(src)/../../combo/common/include \
+                               -I$(src)/../../combo/common/linux/include 
+
+
+obj-$(PRIV_CONFIG) += mtk_fm_priv.o
+mtk_fm_priv-objs       := \
+                               src/$(PRIV_CHIP)/$(PRIV_CHIP)_fm_private.o 
+endif
+
+endif
diff --git a/drivers/mtk_wcn_combo/drv_fm/private/inc/fm_priv_log.h b/drivers/mtk_wcn_combo/drv_fm/private/inc/fm_priv_log.h
new file mode 100755 (executable)
index 0000000..abc68fe
--- /dev/null
@@ -0,0 +1,101 @@
+#ifndef __FM_PRIV_LOG_H__
+#define __FM_PRIV_LOG_H__
+#if 0
+#include "fm_typedef.h"
+
+/******************DBG level ************************/
+#define D_BASE  4
+#define D_IOCTL (1 << (D_BASE+0))
+#define D_RX    (1 << (D_BASE+1))
+#define D_TIMER (1 << (D_BASE+2))
+#define D_BLKC (1 << (D_BASE+3))
+#define D_G0   (1 << (D_BASE+4))
+#define D_G1   (1 << (D_BASE+5))
+#define D_G2   (1 << (D_BASE+6))
+#define D_G3   (1 << (D_BASE+7))
+#define D_G4   (1 << (D_BASE+8))
+#define D_G14  (1 << (D_BASE+9))
+#define D_RAW  (1 << (D_BASE+10))
+#define D_RDS  (1 << (D_BASE+11))
+#define D_INIT (1 << (D_BASE+12))
+#define D_MAIN (1 << (D_BASE+13))
+#define D_CMD  (1 << (D_BASE+14))
+#define D_ALL  0xfffffff0
+
+#define L0 0x00000000 // EMERG, system will crush 
+#define L1 0x00000001 // ALERT, need action in time
+#define L2 0x00000002 // CRIT, important HW or SW operation failed 
+#define L3 0x00000003 // ERR, normal HW or SW ERR 
+#define L4 0x00000004 // WARNING, importan path or somewhere may occurs err
+#define L5 0x00000005 // NOTICE, normal case 
+#define L6 0x00000006 // INFO, print info if need 
+#define L7 0x00000007 // DEBUG, for debug info
+
+#define FM_EMERG    L0
+#define FM_ALERT    L1
+#define FM_CRIT     L2
+#define FM_ERR      L3
+#define FM_WARNING  L4
+#define FM_NOTICE   L5
+#define FM_INFO     L6
+#define FM_DEBUG    L7
+
+extern fm_u32 g_dbg_level;
+
+#define FM_LOG_DBG(flag, fmt, args...) \
+            do{ \
+                if(pub_cb->log && (FM_DEBUG <= (g_dbg_level&0x0000000f)) && ((flag)&0xfffffff0)& g_dbg_level) { \
+                    pub_cb->log("[" #flag "]" fmt, ## args); \
+                } \
+            } while(0)
+        
+#define FM_LOG_INF(flag, fmt, args...) \
+            do{ \
+                if(pub_cb->log && (FM_INFO <= (g_dbg_level&0x0000000f)) && ((flag)&0xfffffff0)& g_dbg_level) { \
+                     pub_cb->log("[" #flag "]" fmt, ## args); \
+                } \
+            } while(0)
+        
+#define FM_LOG_NTC(flag, fmt, args...) \
+            do{ \
+                if(pub_cb->log && (FM_NOTICE <= (g_dbg_level&0x0000000f)) && ((flag)&0xfffffff0)& g_dbg_level) { \
+                     pub_cb->log("[" #flag "]" fmt, ## args); \
+                } \
+            } while(0)
+        
+#define FM_LOG_WAR(flag, fmt, args...) \
+            do{ \
+                if(pub_cb->log && (FM_WARNING <= (g_dbg_level&0x0000000f)) && ((flag)&0xfffffff0)& g_dbg_level) { \
+                     pub_cb->log("[" #flag "]" fmt, ## args); \
+                } \
+            } while(0)
+        
+#define FM_LOG_ERR(flag, fmt, args...) \
+            do{ \
+                if(pub_cb->log && (FM_ERR <= (g_dbg_level&0x0000000f)) && ((flag)&0xfffffff0)& g_dbg_level) { \
+                     pub_cb->log("[" #flag "]" fmt, ## args); \
+                } \
+            } while(0)
+        
+#define FM_LOG_CRT(flag, fmt, args...) \
+            do{ \
+                if(pub_cb->log && (FM_CRIT <= (g_dbg_level&0x0000000f)) && ((flag)&0xfffffff0)& g_dbg_level) { \
+                     pub_cb->log("[" #flag "]" fmt, ## args); \
+                } \
+            } while(0)
+        
+#define FM_LOG_ALT(flag, fmt, args...) \
+            do{ \
+                if(pub_cb->log && (FM_ALERT <= (g_dbg_level&0x0000000f)) && ((flag)&0xfffffff0)& g_dbg_level) { \
+                     pub_cb->log("[" #flag "]" fmt, ## args); \
+                } \
+            } while(0)
+        
+#define FM_LOG_EMG(flag, fmt, args...) \
+            do{ \
+                if(pub_cb->log && (FM_EMERG <= (g_dbg_level&0x0000000f)) && ((flag)&0xfffffff0)& g_dbg_level) { \
+                     pub_cb->log("[" #flag "]" fmt, ## args); \
+                } \
+            } while(0)
+#endif
+#endif //__FM_PRIV_LOG_H__
\ No newline at end of file
diff --git a/drivers/mtk_wcn_combo/drv_fm/private/inc/fm_private.h b/drivers/mtk_wcn_combo/drv_fm/private/inc/fm_private.h
new file mode 100755 (executable)
index 0000000..245a023
--- /dev/null
@@ -0,0 +1,93 @@
+#ifndef __FM_PRIVATE_H__
+#define __FM_PRIVATE_H__
+
+#include "fm_typedef.h"
+
+typedef enum fm_priv_state {
+    UNINITED,
+    INITED
+} fm_priv_state_t;
+
+typedef enum fm_adpll_state {
+    FM_ADPLL_ON,
+    FM_ADPLL_OFF
+} fm_adpll_state_t;
+
+typedef enum fm_hl_dese {
+    FM_HL_DESE_LOW,
+    FM_HL_DESE_HIGH
+} fm_hl_dese_t;
+
+typedef enum fm_adpll_clk {
+    FM_ADPLL_16M,
+    FM_ADPLL_15M
+} fm_adpll_clk_t;
+
+typedef enum fm_mcu_desense {
+    FM_MCU_DESE_ENABLE,
+    FM_MCU_DESE_DISABLE
+} fm_mcu_desense_t;
+
+typedef enum fm_gps_desense {
+    FM_GPS_DESE_ENABLE,
+    FM_GPS_DESE_DISABLE
+} fm_gps_desense_t;
+
+//6620
+typedef struct MT6620fm_priv_cb {
+       //Basic functions.
+       int (*hl_side)(uint16_t freq, int *hl);
+       int (*adpll_freq_avoid)(uint16_t freq, int *freqavoid);
+       int (*mcu_freq_avoid)(uint16_t freq, int *freqavoid);
+    int (*tx_pwr_ctrl)(uint16_t freq, int *ctr);
+    int (*rtc_drift_ctrl)(uint16_t freq, int *ctr);
+    int (*tx_desense_wifi)(uint16_t freq, int *ctr);
+    int (*is_dese_chan)(fm_u16 freq);             // check if this is a de-sense channel
+}MT6620fm_priv_cb_t;
+
+typedef struct MT6620fm_priv{
+    int state;
+    void *data;
+    MT6620fm_priv_cb_t priv_tbl;
+}MT6620fm_priv_t;
+
+//6628
+typedef struct fm_priv_cb {
+    //De-sense functions.
+    fm_s32(*is_dese_chan)(fm_u16 freq);             // check if this is a de-sense channel
+    fm_s32(*hl_dese)(fm_u16 freq, void *arg);       // return value: 0, low side; 1, high side; else error no
+    fm_s32(*fa_dese)(fm_u16 freq, void *arg);       // return value: 0, fa off; 1, fa on; else error no
+    fm_s32(*mcu_dese)(fm_u16 freq, void *arg);      // return value: 0, mcu dese disable; 1, enable; else error no
+    fm_s32(*gps_dese)(fm_u16 freq, void *arg);      // return value: 0,mcu dese disable; 1, enable; else error no
+    fm_u16(*chan_para_get)(fm_u16 freq);            //get channel parameter, HL side/ FA / ATJ
+} fm_priv_cb_t;
+
+typedef struct fm_priv {
+    fm_s32 state;
+    fm_priv_cb_t priv_tbl;
+    void *data;
+} fm_priv_t;
+
+typedef struct fm_pub_cb {
+    //Basic functions.
+    fm_s32(*read)(fm_u8 addr, fm_u16 *val);
+    fm_s32(*write)(fm_u8 addr, fm_u16 val);
+    fm_s32(*setbits)(fm_u8 addr, fm_u16 bits, fm_u16 mask);
+    fm_s32(*rampdown)(void);
+    fm_s32(*msdelay)(fm_u32 val);
+    fm_s32(*usdelay)(fm_u32 val);
+    fm_s32(*log)(const fm_s8 *arg1, ...);
+} fm_pub_cb_t;
+
+typedef struct fm_pub {
+    fm_s32 state;
+    void *data;
+    struct fm_pub_cb pub_tbl;
+} fm_pub_t;
+
+
+#if 0//(!defined(MT6620_FM)&&!defined(MT6628_FM))
+extern fm_s32 fm_priv_register(struct fm_priv *pri, struct fm_pub *pub);
+extern fm_s32 fm_priv_unregister(struct fm_priv *pri, struct fm_pub *pub);
+#endif
+#endif //__FM_PRIVATE_H__
\ No newline at end of file
diff --git a/drivers/mtk_wcn_combo/drv_wlan/Makefile b/drivers/mtk_wcn_combo/drv_wlan/Makefile
new file mode 100755 (executable)
index 0000000..5c4e9ee
--- /dev/null
@@ -0,0 +1,6 @@
+#ifeq ($(MTK_WLAN_SUPPORT), yes)
+    obj-$(CONFIG_MTK_COMBO_WIFI) += mt6620/
+#    obj-$(CONFIG_MTK_COMBO_WIFI) += mt6628/
+#endif
+
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/Makefile b/drivers/mtk_wcn_combo/drv_wlan/mt6620/Makefile
new file mode 100755 (executable)
index 0000000..2968515
--- /dev/null
@@ -0,0 +1 @@
+obj-$(CONFIG_MTK_COMBO_WIFI) += wlan/
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/Makefile b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/Makefile
new file mode 100755 (executable)
index 0000000..1dc8a62
--- /dev/null
@@ -0,0 +1,142 @@
+# ---------------------------------------------------
+# Compile Options
+# ---------------------------------------------------
+
+#include $(MTK_PATH_BUILD)/Makefile
+ccflags-y += -DLINUX -DMT6620
+
+ifeq ($(MTK_WAPI_SUPPORT), yes)
+    ccflags-y += -DCFG_SUPPORT_WAPI=1
+else
+    ccflags-y += -DCFG_SUPPORT_WAPI=0
+endif
+
+ifeq ($(HAVE_XLOG_FEATURE), yes)
+    ccflags-y += -DCFG_SUPPORT_XLOG=1
+else
+    ccflags-y += -DCFG_SUPPORT_XLOG=0
+endif
+
+ifeq ($(HAVE_AEE_FEATURE), yes)
+    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
+
+MODULE_NAME := wlan_mt6620
+
+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/sdio/include
+ccflags-y += -I$(src)/include -I$(src)/include/nic -I$(src)/include/mgmt
+
+obj-$(CONFIG_MTK_COMBO_WIFI) += $(MODULE_NAME).o
+#obj-m += $(MODULE_NAME).o
+
+# ---------------------------------------------------
+# Directory List
+# ---------------------------------------------------
+COMMON_DIR  := common/
+OS_DIR      := os/linux/
+HIF_DIR            := os/linux/hif/sdio/
+NIC_DIR     := nic/
+MGMT_DIR    := mgmt/
+
+
+# ---------------------------------------------------
+# Objects List
+# ---------------------------------------------------
+
+COMMON_OBJS := $(COMMON_DIR)dump.o \
+                       $(COMMON_DIR)wlan_lib.o \
+                       $(COMMON_DIR)wlan_oid.o \
+                       $(COMMON_DIR)wlan_bow.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)platform.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)roaming_fsm.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 ($(MTK_WAPI_SUPPORT), yes)
+MGMT_OBJS += $(MGMT_DIR)wapi.o
+endif
+
+ifeq ($(WLAN_PROC), y)
+OS_OBJS += gl_proc.o
+endif
+
+HIF_OBJS :=  $(HIF_DIR)arm.o \
+             $(HIF_DIR)sdio.o
+
+$(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/mtk_wcn_combo/drv_wlan/mt6620/wlan/common/dump.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/common/dump.c
new file mode 100755 (executable)
index 0000000..95f2d7f
--- /dev/null
@@ -0,0 +1,539 @@
+/*
+** $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
+********************************************************************************
+*/
+#if DBG
+/*----------------------------------------------------------------------------*/
+/*!
+* \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: %08lx, Length: %ld\n", (UINT_32)pucStartAddr, u4Length);
+
+    while (u4Length > 0) {
+        if (u4Length >= 16) {
+            LOG_FUNC("(%08lx) %02x %02x %02x %02x  %02x %02x %02x %02x - %02x %02x %02x %02x  %02x %02x %02x %02x\n",
+                (UINT_32)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("(%08lx) %02x\n",
+                    (UINT_32)pucStartAddr,
+                    pucStartAddr[ 0]);
+                break;
+            case 2:
+                LOG_FUNC("(%08lx) %02x %02x\n",
+                    (UINT_32)pucStartAddr,
+                    pucStartAddr[ 0], pucStartAddr[ 1]);
+                break;
+            case 3:
+                LOG_FUNC("(%08lx) %02x %02x %02x\n",
+                    (UINT_32)pucStartAddr,
+                    pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2]);
+                break;
+            case 4:
+                LOG_FUNC("(%08lx) %02x %02x %02x %02x\n",
+                    (UINT_32)pucStartAddr,
+                    pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3]);
+                break;
+            case 5:
+                LOG_FUNC("(%08lx) %02x %02x %02x %02x  %02x\n",
+                    (UINT_32)pucStartAddr,
+                    pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3],
+                    pucStartAddr[ 4]);
+                break;
+            case 6:
+                LOG_FUNC("(%08lx) %02x %02x %02x %02x  %02x %02x\n",
+                    (UINT_32)pucStartAddr,
+                    pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3],
+                    pucStartAddr[ 4], pucStartAddr[ 5]);
+                break;
+            case 7:
+                LOG_FUNC("(%08lx) %02x %02x %02x %02x  %02x %02x %02x\n",
+                    (UINT_32)pucStartAddr,
+                    pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3],
+                    pucStartAddr[ 4], pucStartAddr[ 5], pucStartAddr[ 6]);
+                break;
+            case 8:
+                LOG_FUNC("(%08lx) %02x %02x %02x %02x  %02x %02x %02x %02x\n",
+                    (UINT_32)pucStartAddr,
+                    pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3],
+                    pucStartAddr[ 4], pucStartAddr[ 5], pucStartAddr[ 6], pucStartAddr[ 7]);
+                break;
+            case 9:
+                LOG_FUNC("(%08lx) %02x %02x %02x %02x  %02x %02x %02x %02x - %02x\n",
+                    (UINT_32)pucStartAddr,
+                    pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3],
+                    pucStartAddr[ 4], pucStartAddr[ 5], pucStartAddr[ 6], pucStartAddr[ 7],
+                    pucStartAddr[ 8]);
+                break;
+            case 10:
+                LOG_FUNC("(%08lx) %02x %02x %02x %02x  %02x %02x %02x %02x - %02x %02x\n",
+                    (UINT_32)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("(%08lx) %02x %02x %02x %02x  %02x %02x %02x %02x - %02x %02x %02x\n",
+                    (UINT_32)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("(%08lx) %02x %02x %02x %02x  %02x %02x %02x %02x - %02x %02x %02x %02x\n",
+                    (UINT_32)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("(%08lx) %02x %02x %02x %02x  %02x %02x %02x %02x - %02x %02x %02x %02x  %02x\n",
+                    (UINT_32)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("(%08lx) %02x %02x %02x %02x  %02x %02x %02x %02x - %02x %02x %02x %02x  %02x %02x\n",
+                    (UINT_32)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("(%08lx) %02x %02x %02x %02x  %02x %02x %02x %02x - %02x %02x %02x %02x  %02x %02x %02x\n",
+                    (UINT_32)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");
+
+    return;
+} /* 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: %08lx, Length: %ld\n", (UINT_32)pu4StartAddr, u4Length);
+
+    if (IS_NOT_ALIGN_4((UINT_32)pu4StartAddr)) {
+        UINT_32 u4ProtrudeLen = sizeof(UINT_32) - ((UINT_32)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("(%08lx) %02x------\n",
+                   (UINT_32)pu4StartAddr,
+                   pucAddr[0]);
+                break;
+            case 2:
+                LOG_FUNC("(%08lx) %02x%02x----\n",
+                   (UINT_32)pu4StartAddr,
+                   pucAddr[1], pucAddr[0]);
+                break;
+            case 3:
+                LOG_FUNC("(%08lx) %02x%02x%02x--\n",
+                   (UINT_32)pu4StartAddr,
+                   pucAddr[2], pucAddr[1], pucAddr[0]);
+                break;
+            default:
+                break;
+        }
+
+        u4Length -= u4ProtrudeLen;
+        pu4StartAddr = (PUINT_32)((UINT_32)pu4StartAddr + u4ProtrudeLen);
+    }
+
+    while (u4Length > 0) {
+        if (u4Length >= 16) {
+            LOG_FUNC("(%08lx) %08lx %08lx %08lx %08lx\n",
+                (UINT_32)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("(%08lx) ------%02x\n",
+                    (UINT_32)pu4StartAddr,
+                    pucAddr[0]);
+                 break;
+            case 2:
+                 pucAddr = (PUINT_8) &pu4StartAddr[0];
+                 LOG_FUNC("(%08lx) ----%02x%02x\n",
+                    (UINT_32)pu4StartAddr,
+                    pucAddr[1], pucAddr[0]);
+                 break;
+            case 3:
+                 pucAddr = (PUINT_8) &pu4StartAddr[0];
+                 LOG_FUNC("(%08lx) --%02x%02x%02x\n",
+                    (UINT_32)pu4StartAddr,
+                    pucAddr[2], pucAddr[1], pucAddr[0]);
+                 break;
+            case 4:
+                 LOG_FUNC("(%08lx) %08lx\n",
+                    (UINT_32)pu4StartAddr,
+                    pu4StartAddr[0]);
+                 break;
+            case 5:
+                 pucAddr = (PUINT_8) &pu4StartAddr[1];
+                 LOG_FUNC("(%08lx) %08lx ------%02x\n",
+                    (UINT_32)pu4StartAddr,
+                    pu4StartAddr[0],
+                    pucAddr[0]);
+                 break;
+            case 6:
+                 pucAddr = (PUINT_8) &pu4StartAddr[1];
+                 LOG_FUNC("(%08lx) %08lx ----%02x%02x\n",
+                    (UINT_32)pu4StartAddr,
+                    pu4StartAddr[0],
+                    pucAddr[1], pucAddr[0]);
+                 break;
+            case 7:
+                 pucAddr = (PUINT_8) &pu4StartAddr[1];
+                 LOG_FUNC("(%08lx) %08lx --%02x%02x%02x\n",
+                    (UINT_32)pu4StartAddr,
+                    pu4StartAddr[0],
+                    pucAddr[2], pucAddr[1], pucAddr[0]);
+                 break;
+            case 8:
+                 LOG_FUNC("(%08lx) %08lx %08lx\n",
+                    (UINT_32)pu4StartAddr,
+                    pu4StartAddr[0], pu4StartAddr[1]);
+                 break;
+            case 9:
+                 pucAddr = (PUINT_8) &pu4StartAddr[2];
+                 LOG_FUNC("(%08lx) %08lx %08lx ------%02x\n",
+                    (UINT_32)pu4StartAddr,
+                    pu4StartAddr[0], pu4StartAddr[1],
+                    pucAddr[0]);
+                 break;
+            case 10:
+                 pucAddr = (PUINT_8) &pu4StartAddr[2];
+                 LOG_FUNC("(%08lx) %08lx %08lx ----%02x%02x\n",
+                    (UINT_32)pu4StartAddr,
+                    pu4StartAddr[0], pu4StartAddr[1],
+                    pucAddr[1], pucAddr[0]);
+                 break;
+            case 11:
+                 pucAddr = (PUINT_8) &pu4StartAddr[2];
+                 LOG_FUNC("(%08lx) %08lx %08lx --%02x%02x%02x\n",
+                    (UINT_32)pu4StartAddr,
+                    pu4StartAddr[0], pu4StartAddr[1],
+                    pucAddr[2], pucAddr[1], pucAddr[0]);
+                 break;
+            case 12:
+                 LOG_FUNC("(%08lx) %08lx %08lx %08lx\n",
+                    (UINT_32)pu4StartAddr,
+                    pu4StartAddr[0], pu4StartAddr[1], pu4StartAddr[2]);
+                 break;
+            case 13:
+                 pucAddr = (PUINT_8) &pu4StartAddr[3];
+                 LOG_FUNC("(%08lx) %08lx %08lx %08lx ------%02x\n",
+                    (UINT_32)pu4StartAddr,
+                    pu4StartAddr[0], pu4StartAddr[1], pu4StartAddr[2],
+                    pucAddr[0]);
+                 break;
+            case 14:
+                 pucAddr = (PUINT_8) &pu4StartAddr[3];
+                 LOG_FUNC("(%08lx) %08lx %08lx %08lx ----%02x%02x\n",
+                     (UINT_32)pu4StartAddr,
+                     pu4StartAddr[0], pu4StartAddr[1], pu4StartAddr[2],
+                     pucAddr[1], pucAddr[0]);
+                 break;
+            case 15:
+                 pucAddr = (PUINT_8) &pu4StartAddr[3];
+                 LOG_FUNC("(%08lx) %08lx %08lx %08lx --%02x%02x%02x\n",
+                     (UINT_32)pu4StartAddr,
+                     pu4StartAddr[0], pu4StartAddr[1], pu4StartAddr[2],
+                     pucAddr[2], pucAddr[1], pucAddr[0]);
+                 break;
+            default:
+                break;
+            }
+            u4Length = 0;
+        }
+    }
+
+    return;
+} /* end of dumpMemory32() */
+#elif CFG_SUPPORT_XLOG
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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 UINT_32  log_level,
+    IN PUINT_8  pucStartAddr,
+    IN UINT_32  u4Length
+    )
+{
+    ASSERT(pucStartAddr);
+
+    if (log_level == ANDROID_LOG_ERROR) {
+        xlog_printk(ANDROID_LOG_ERROR, XLOG_TAG, "DUMP8 ADDRESS: %08lx, Length: %ld\n", (UINT_32)pucStartAddr, u4Length);
+    }
+    else if (log_level == ANDROID_LOG_WARN) {
+        xlog_printk(ANDROID_LOG_WARN, XLOG_TAG, "DUMP8 ADDRESS: %08lx, Length: %ld\n", (UINT_32)pucStartAddr, u4Length);
+    }
+    else if (log_level == ANDROID_LOG_INFO) {
+        xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, "DUMP8 ADDRESS: %08lx, Length: %ld\n", (UINT_32)pucStartAddr, u4Length);
+    }
+    else if (log_level == ANDROID_LOG_DEBUG) {
+        xlog_printk(ANDROID_LOG_DEBUG, XLOG_TAG, "DUMP8 ADDRESS: %08lx, Length: %ld\n", (UINT_32)pucStartAddr, u4Length);
+    }
+    else if (log_level == ANDROID_LOG_VERBOSE) {
+        xlog_printk(ANDROID_LOG_VERBOSE, XLOG_TAG, "DUMP8 ADDRESS: %08lx, Length: %ld\n", (UINT_32)pucStartAddr, u4Length);
+    }
+
+    while (u4Length > 0) {
+        if (u4Length >= 16) {
+            XLOG_FUNC(log_level, "%02x %02x %02x %02x  %02x %02x %02x %02x - %02x %02x %02x %02x  %02x %02x %02x %02x\n",
+                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:
+                XLOG_FUNC(log_level, "%02x\n",
+                    pucStartAddr[ 0]);
+                break;
+            case 2:
+                XLOG_FUNC(log_level, "%02x %02x\n",
+                    pucStartAddr[ 0], pucStartAddr[ 1]);
+                break;
+            case 3:
+                XLOG_FUNC(log_level, "%02x %02x %02x\n",
+                    pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2]);
+                break;
+            case 4:
+                XLOG_FUNC(log_level, "%02x %02x %02x %02x\n",
+                    pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3]);
+                break;
+            case 5:
+                XLOG_FUNC(log_level, "%02x %02x %02x %02x  %02x\n",
+                    pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3],
+                    pucStartAddr[ 4]);
+                break;
+            case 6:
+                XLOG_FUNC(log_level, "%02x %02x %02x %02x  %02x %02x\n",
+                    pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3],
+                    pucStartAddr[ 4], pucStartAddr[ 5]);
+                break;
+            case 7:
+                XLOG_FUNC(log_level, "%02x %02x %02x %02x  %02x %02x %02x\n",
+                    pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3],
+                    pucStartAddr[ 4], pucStartAddr[ 5], pucStartAddr[ 6]);
+                break;
+            case 8:
+                XLOG_FUNC(log_level, "%02x %02x %02x %02x  %02x %02x %02x %02x\n",
+                    pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3],
+                    pucStartAddr[ 4], pucStartAddr[ 5], pucStartAddr[ 6], pucStartAddr[ 7]);
+                break;
+            case 9:
+                XLOG_FUNC(log_level, "%02x %02x %02x %02x  %02x %02x %02x %02x - %02x\n",
+                    pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3],
+                    pucStartAddr[ 4], pucStartAddr[ 5], pucStartAddr[ 6], pucStartAddr[ 7],
+                    pucStartAddr[ 8]);
+                break;
+            case 10:
+                XLOG_FUNC(log_level, "%02x %02x %02x %02x  %02x %02x %02x %02x - %02x %02x\n",
+                    pucStartAddr[ 0], pucStartAddr[ 1], pucStartAddr[ 2], pucStartAddr[ 3],
+                    pucStartAddr[ 4], pucStartAddr[ 5], pucStartAddr[ 6], pucStartAddr[ 7],
+                    pucStartAddr[ 8], pucStartAddr[ 9]);
+                break;
+            case 11:
+                XLOG_FUNC(log_level, "%02x %02x %02x %02x  %02x %02x %02x %02x - %02x %02x %02x\n",
+                    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:
+                XLOG_FUNC(log_level, "%02x %02x %02x %02x  %02x %02x %02x %02x - %02x %02x %02x %02x\n",
+                    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:
+                XLOG_FUNC(log_level, "%02x %02x %02x %02x  %02x %02x %02x %02x - %02x %02x %02x %02x  %02x\n",
+                    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:
+                XLOG_FUNC(log_level, "%02x %02x %02x %02x  %02x %02x %02x %02x - %02x %02x %02x %02x  %02x %02x\n",
+                    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:
+                XLOG_FUNC(log_level, "%02x %02x %02x %02x  %02x %02x %02x %02x - %02x %02x %02x %02x  %02x %02x %02x\n",
+                    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;
+        }
+    }
+
+
+    return;
+} /* end of dumpMemory8() */
+#endif /* DBG */
+
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/common/wlan_bow.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/common/wlan_bow.c
new file mode 100755 (executable)
index 0000000..41b179d
--- /dev/null
@@ -0,0 +1,3898 @@
+/*
+** $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
+
+#if CFG_BOW_TEST
+extern UINT_32 g_arBowRevPalPacketTime[32];
+#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
+*******************************************************************************
+*/
+
+static UINT_32         g_u4LinkCount = 0;
+static UINT_32         g_u4Beaconing = 0;
+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);
+
+    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, EVENT, ("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, EVENT, ("bowCmdGetMacStatus, Get channel list. Current number of channel, %d.\n", ucNumOfChannel));
+#endif
+
+        rlmDomainGetChnlList(prAdapter, BAND_2G4, MAX_BOW_NUMBER_OF_CHANNEL_2G4, &ucNumOfChannel, aucChannelList);
+
+        if (ucNumOfChannel > 0) {
+            for (idx = 0; idx < ucNumOfChannel/*MAX_BOW_NUMBER_OF_CHANNEL_2G4*/; idx++)
+        {
+            prMacStatus->arChannelList[idx].ucChannelBand = aucChannelList[idx].eBand;
+            prMacStatus->arChannelList[idx].ucChannelNum = aucChannelList[idx].ucChannelNum;
+        }
+
+            prMacStatus->ucNumOfChannel = ucNumOfChannel;
+    }
+
+        rlmDomainGetChnlList(prAdapter, BAND_5G, MAX_BOW_NUMBER_OF_CHANNEL_5G, &ucNumOfChannel, aucChannelList);
+
+        if (ucNumOfChannel > 0) {       
+            for (idx = 0; idx < ucNumOfChannel/*MAX_BOW_NUMBER_OF_CHANNEL_5G*/; 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, EVENT, ("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, EVENT, ("prMacStatus->ucNumOfChannel, eBand, prMacStatus->arChannelList, %x, %x, %x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x.\n",
+        prMacStatus->ucNumOfChannel,
+        prMacStatus->arChannelList[0].ucChannelBand,
+        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, EVENT, ("prMacStatus->ucNumOfChannel, %x.\n", prMacStatus->ucNumOfChannel));
+    DBGLOG(BOW, EVENT, ("prMacStatus->arChannelList[0].ucChannelBand, %x.\n", prMacStatus->arChannelList[0].ucChannelBand));
+    DBGLOG(BOW, EVENT, ("prMacStatus->arChannelList[0].ucChannelNum, %x.\n", prMacStatus->arChannelList[0].ucChannelNum));
+    DBGLOG(BOW, EVENT, ("prMacStatus->ucAvailability, %x.\n", prMacStatus->ucAvailability));
+    DBGLOG(BOW, EVENT, ("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;
+
+    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,
+                (UINT_32)NULL);
+
+        cnmTimerInitTimer(prAdapter,
+                &prBowFsmInfo->rChGrantedTimer,
+                (PFN_MGMT_TIMEOUT_FUNC)bowChGrantedTimeout,
+                (UINT_32)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;
+    }
+    else
+    {
+        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);
+    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);
+    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);
+    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;
+    BOOL 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);
+    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);
+
+    /*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;
+    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);
+    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);
+    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);
+    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);
+    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)));
+
+    return;
+}
+
+
+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);
+
+    }
+
+    return;
+}
+
+
+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
+        prBssInfo->ucPhyTypeSet = prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11BGN; /* Depend on eBand */
+        prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; /* Depend on eCurrentOPMode and ucPhyTypeSet */
+
+        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)
+        {
+        prBssInfo->ucPhyTypeSet = PHY_TYPE_SET_802_11BG; /* Depend on eBand */
+        prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; /* Depend on eCurrentOPMode and ucPhyTypeSet */
+
+            prBssInfo->u2BSSBasicRateSet = BASIC_RATE_SET_ERP; //RATE_SET_ERP;
+        prBssInfo->u2OperationalRateSet = RATE_SET_ERP;
+            prBssInfo->ucNonHTBasicPhyType = PHY_TYPE_ERP_INDEX;
+        }
+        else
+        {
+            //prBssInfo->ucPhyTypeSet = PHY_TYPE_SET_802_11BG; /* Depend on eBand */
+            //prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; /* Depend on eCurrentOPMode and ucPhyTypeSet */
+            prBssInfo->ucPhyTypeSet = PHY_TYPE_SET_802_11A; /* Depend on eBand */
+            prBssInfo->ucConfigAdHocAPMode = AP_MODE_11A; /* Depend on eCurrentOPMode and ucPhyTypeSet */
+
+            //prBssInfo->u2BSSBasicRateSet = BASIC_RATE_SET_ERP; //RATE_SET_ERP;
+            //prBssInfo->u2OperationalRateSet = RATE_SET_ERP;
+
+            prBssInfo->u2BSSBasicRateSet = BASIC_RATE_SET_OFDM; //RATE_SET_ERP;
+            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 {
+        //bowRequestCh(prAdapter);
+    }
+#endif
+    return;
+}
+
+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;
+        }
+    }
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @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)((UINT_32)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 UINT_32 u4Param
+    )
+{
+    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 */
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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;
+    }
+    else
+    {
+        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
+        }
+    }
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @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);
+
+    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));
+    printk("BoW trigger SAA ["MACSTR"]\n", MAC2STR(prStaRec->aucMacAddr));
+#endif
+
+    mboxSendMsg(prAdapter,
+            MBOX_ID_0,
+            (P_MSG_HDR_T) prJoinReqMsg,
+            MSG_SEND_METHOD_BUF);
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @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 avaliable 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"));
+            printk("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));
+    }
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @brief This function will indiate 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"));
+    printk("BoW AAA TxFail, target state %d\n", prStaRec->ucStaState+1);
+#endif
+
+    prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]);
+    bssRemoveStaRecFromClientList(prAdapter, prBssInfo, prStaRec);
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @brief This function will indiate 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"));
+    printk("BoW AAA complete ["MACSTR"]\n", MAC2STR(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 = 0;
+
+    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);
+        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 avaliable highest rate*/
+        if(prStaRec->u2DesiredNonHTRateSet == 0) {
+            UINT_8 ucHighestRateIndex;
+            if (rateGetHighestRateIndexFromRateSet(prBowBssInfo->u2OperationalRateSet, &ucHighestRateIndex)) {
+                prStaRec->u2DesiredNonHTRateSet = BIT(ucHighestRateIndex);
+            } else {
+                /*If no avaliable 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 = 0;
+
+    /* 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.
+              */
+        ASSERT(prStaRec);
+        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
+        printk("BoW Channel [GIVE UP:%d]\n", ucTokenID);
+        printk("[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
+    printk("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);
+        }
+
+    return;
+} /* 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
+        printk("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
+        prMsgChReq->ucPrimaryChannel  = prBowFsmInfo->ucPrimaryChannel;  //prBowFsmInfo->prTargetBssDesc->ucChannelNum;
+        prMsgChReq->eRfSco = CHNL_EXT_SCN; //prBowFsmInfo->prTargetBssDesc->eSco;
+        prMsgChReq->eRfBand = prBowFsmInfo->eBand;  //prBowFsmInfo->prTargetBssDesc->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
+        printk("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);
+    }
+
+    return;
+} /* 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 UINT_32 u4Param
+    )
+{
+    P_BOW_FSM_INFO_T prBowFsmInfo;
+    ENUM_BOW_DEVICE_STATE eFsmState;
+
+    ASSERT(prAdapter);
+
+    prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo);
+
+#if CFG_BOW_TEST
+    printk("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));
+        printk("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
+    printk("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));
+            printk("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
+        printk("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/mtk_wcn_combo/drv_wlan/mt6620/wlan/common/wlan_lib.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/common/wlan_lib.c
new file mode 100755 (executable)
index 0000000..604d793
--- /dev/null
@@ -0,0 +1,5568 @@
+/*
+** $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 occured.
+ *
+ * 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) Chnage 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 continous memory demands
+ * separate kalMemAlloc() into virtually-continous and physically-continous 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 adress & 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
+};
+
+#if QM_TEST_MODE
+extern QUE_MGT_T g_rQM;
+#endif
+/*******************************************************************************
+*                             D A T A   T Y P E S
+********************************************************************************
+*/
+typedef struct _CODE_MAPPING_T {
+    UINT_32         u4RegisterValue;
+    INT_32         u4TxpowerOffset;
+} 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
+********************************************************************************
+*/
+/*----------------------------------------------------------------------------*/
+/*!
+* \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 */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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;
+        }
+
+#if QM_TEST_MODE
+        g_rQM.prAdapter = prAdpater;
+#endif
+        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));
+
+    return;
+}
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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
+#if (defined(MT5931) && (!CFG_SUPPORT_BCM_BWCS))
+    PARAM_PTA_IPC_T rBwcsPta;
+    UINT_32 u4SetInfoLen;
+#endif
+
+    ASSERT(prAdapter);
+
+    DEBUGFUNC("wlanAdapterStart");
+
+    //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;
+
+    do {
+        if ( (u4Status = nicAllocateAdapterMemory(prAdapter)) != WLAN_STATUS_SUCCESS ) {
+            DBGLOG(INIT, ERROR, ("nicAllocateAdapterMemory Error!\n"));
+            u4Status = WLAN_STATUS_FAILURE;
+            break;
+        }
+
+        prAdapter->u4OsPacketFilter = PARAM_PACKET_FILTER_SUPPORTED;
+
+#if defined(MT6620) || defined(MT6628)
+        DBGLOG(INIT, TRACE, ("wlanAdapterStart(): Acquiring LP-OWN\n"));
+        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;
+            break;
+        }
+
+        //4 <1> Initialize the Adapter
+        if ( (u4Status = nicInitializeAdapter(prAdapter)) != WLAN_STATUS_SUCCESS ) {
+            DBGLOG(INIT, ERROR, ("nicInitializeAdapter failed!\n"));
+            u4Status = WLAN_STATUS_FAILURE;
+            break;
+        }
+#endif
+
+        //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 defined(MT6620) || defined(MT6628)
+        if (pvFwImageMapFile) {
+            /* 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) {
+                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(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!\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,
+                        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) {
+                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
+        }
+        else {
+            DBGLOG(INIT, ERROR, ("No Firmware found!\n"));
+            u4Status = WLAN_STATUS_FAILURE;
+            break;
+        }
+
+        /* 4. send Wi-Fi Start command */
+        #if CFG_OVERRIDE_FW_START_ADDRESS
+        wlanConfigWifiFunc(prAdapter,
+                TRUE,
+                prRegInfo->u4StartAddress);
+        #else
+        wlanConfigWifiFunc(prAdapter,
+                FALSE,
+                0);
+        #endif
+    #elif defined(MT5931)
+        if (pvFwImageMapFile) {
+            DBGLOG(INIT, TRACE, ("Download Address: 0x%08X\n", prRegInfo->u4LoadAddress));
+            DBGLOG(INIT, TRACE, ("Firmware Length:  0x%08X\n", u4FwImageFileLength));
+
+            do {
+#if CFG_SUPPORT_WHOLE_CHIP_RESET
+#define RESET_RDY_INTERVAL (120)
+
+                /* 1.0 whole-chip reset except HIFSYS */
+                HAL_MCR_WR(prAdapter, MCR_WMCSR, WMCSR_CHIP_RST);
+                HAL_MCR_WR(prAdapter, MCR_WMCSR, 0);
+
+                /* 1.0.1 delay for EEIF ready */
+                kalMsleep(RESET_RDY_INTERVAL);
+#endif
+
+                /* 1.1 wait for INIT_RDY */
+                i = 0;
+                while(1) {
+                    HAL_MCR_RD(prAdapter, MCR_WMCSR, &u4Value);
+
+                    if (u4Value & WMCSR_INI_RDY) {
+                        DBGLOG(INIT, TRACE, ("INIT-RDY detected\n"));
+                        break;
+                    }
+                    else if(kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE
+                            || fgIsBusAccessFailed == TRUE) {
+                        u4Status = WLAN_STATUS_FAILURE;
+                        break;
+                    }
+                    else if(i >= CFG_RESPONSE_POLLING_TIMEOUT) {
+                        DBGLOG(INIT, ERROR, ("Waiting for Init Ready bit: Timeout\n"));
+                        u4Status = WLAN_STATUS_FAILURE;
+                        break;
+                    }
+                    else {
+                        i++;
+                        kalMsleep(10);
+                    }
+                }
+
+                if(u4Status != WLAN_STATUS_SUCCESS) {
+                    break;
+                }
+
+                /* 1.2 set KSEL/FLEN */
+                HAL_MCR_WR(prAdapter, MCR_FWCFG, u4FwImageFileLength >> 6);
+
+                /* 1.3 enable FWDL_EN */
+                HAL_MCR_WR(prAdapter, MCR_WMCSR, WMCSR_FWDLEN);
+
+                /* 1.4 wait for PLL_RDY */
+                i = 0;
+                while(1) {
+                    HAL_MCR_RD(prAdapter, MCR_WMCSR, &u4Value);
+
+                    if (u4Value & WMCSR_PLLRDY) {
+                        DBGLOG(INIT, TRACE, ("PLL-RDY detected\n"));
+                        break;
+                    }
+                    else if(kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE
+                            || fgIsBusAccessFailed == TRUE) {
+                        u4Status = WLAN_STATUS_FAILURE;
+                        break;
+                    }
+                    else if(i >= CFG_RESPONSE_POLLING_TIMEOUT) {
+                        DBGLOG(INIT, ERROR, ("Waiting for PLL Ready bit: Timeout\n"));
+                        u4Status = WLAN_STATUS_FAILURE;
+                        break;
+                    }
+                    else {
+                        i++;
+                        kalMsleep(10);
+                    }
+                }
+
+                if(u4Status != WLAN_STATUS_SUCCESS) {
+                    break;
+                }
+
+                /* 2.1 turn on HIFSYS firmware download mode */
+                HAL_MCR_WR(prAdapter, MCR_FWDLSR, FWDLSR_FWDL_MODE);
+
+                /* 2.2 set starting address */
+                u4FwLoadAddr = prRegInfo->u4LoadAddress;
+                HAL_MCR_WR(prAdapter, MCR_FWDLDSAR, u4FwLoadAddr);
+
+                /* 3. upload firmware */
+                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;
+                    }
+                }
+
+                if(u4Status != WLAN_STATUS_SUCCESS) {
+                    break;
+                }
+
+                /* 4.1 poll FWDL_OK & FWDL_FAIL bits */
+                i = 0;
+                while(1) {
+                    HAL_MCR_RD(prAdapter, MCR_WMCSR, &u4Value);
+
+                    if (u4Value & WMCSR_DL_OK) {
+                         DBGLOG(INIT, TRACE, ("DL_OK detected\n"));
+                        break;
+                    }
+                    else if(kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE
+                            || fgIsBusAccessFailed == TRUE
+                            || (u4Value & WMCSR_DL_FAIL)) {
+                        DBGLOG(INIT, ERROR, ("DL_FAIL detected: 0x%08X\n", u4Value));
+                        u4Status = WLAN_STATUS_FAILURE;
+                        break;
+                    }
+                    else if(i >= CFG_RESPONSE_POLLING_TIMEOUT) {
+                        DBGLOG(INIT, ERROR, ("Waiting for DL_OK/DL_FAIL bit: Timeout\n"));
+                        u4Status = WLAN_STATUS_FAILURE;
+                        break;
+                    }
+                    else {
+                        i++;
+                        kalMsleep(10);
+                    }
+                }
+
+                if(u4Status != WLAN_STATUS_SUCCESS) {
+                    break;
+                }
+
+                /* 4.2 turn off HIFSYS download mode */
+                HAL_MCR_WR(prAdapter, MCR_FWDLSR, 0);
+
+            } while (FALSE);
+
+            if(u4Status != WLAN_STATUS_SUCCESS) {
+                break;
+            }
+
+            /* 5. disable interrupt */
+            nicDisableInterrupt(prAdapter);
+        }
+        else {
+            DBGLOG(INIT, ERROR, ("No Firmware found!\n"));
+            u4Status = WLAN_STATUS_FAILURE;
+            break;
+        }
+    #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;
+                break;
+            }
+            else if(i >= CFG_RESPONSE_POLLING_TIMEOUT) {
+                UINT_32     u4MailBox0;
+
+                nicGetMailbox(prAdapter, 0, &u4MailBox0);
+                DBGLOG(INIT, ERROR, ("Waiting for Ready bit: Timeout, ID=%d\n",
+                        (u4MailBox0 & 0x0000FFFF)));
+                u4Status = WLAN_STATUS_FAILURE;
+                break;
+            }
+            else {
+                i++;
+                kalMsleep(10);
+            }
+        }
+
+#if defined(MT5931)
+        // Acquire LP-OWN
+        DBGLOG(INIT, TRACE, ("wlanAdapterStart(): Acquiring LP-OWN\n"));
+        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;
+            break;
+        }
+
+        //4 <1> Initialize the Adapter
+        if ( (u4Status = nicInitializeAdapter(prAdapter)) != WLAN_STATUS_SUCCESS ) {
+            DBGLOG(INIT, ERROR, ("nicInitializeAdapter failed!\n"));
+            u4Status = WLAN_STATUS_FAILURE;
+            break;
+        }
+
+        /* post initialization for MT5931 due to some CR is only accessible after driver own */
+        nicRxPostInitialize(prAdapter);
+#endif
+
+        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);
+
+#if CFG_SUPPORT_OSC_SETTING && defined(MT5931)
+            wlanSetMcuOscStableTime(prAdapter, 0);
+#endif
+
+            /* 3. query for permanent address by polling */
+            wlanQueryPermanentAddress(prAdapter);
+
+#if (CFG_SUPPORT_NIC_CAPABILITY == 1)
+            /* 4. query for NIC capability */
+            wlanQueryNicCapability(prAdapter);
+#endif
+
+            /* 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) {
+            break;
+        }
+
+        /* OID timeout timer initialize */
+        cnmTimerInitTimer(prAdapter,
+                &prAdapter->rOidTimeoutTimer,
+                (PFN_MGMT_TIMEOUT_FUNC)wlanReleasePendingOid,
+                (UINT_32)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;
+
+#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
+        {/*CR:WCNAE00007101*/
+            struct net_device *prDev = prAdapter->prGlueInfo->prDevHandler;
+
+            if (prDev != NULL) {
+                glBusSetIrq(prDev, NULL, prAdapter->prGlueInfo );
+            }
+            else {
+                printk(KERN_INFO "Skip glBusSetIrq because of the prDev\n");
+            }
+        }
+        nicConfigPowerSaveProfile(
+            prAdapter,
+            NETWORK_TYPE_AIS_INDEX, //FIXIT
+            prAdapter->u4PowerMode,
+            FALSE);
+        }
+
+#endif
+
+#if CFG_SUPPORT_NVRAM
+        /* load manufacture data */
+        wlanLoadManufactureData(prAdapter, prRegInfo);
+#endif
+
+#if (defined(MT5931) && (!CFG_SUPPORT_BCM_BWCS))
+        //Enable DPD calibration.
+        rBwcsPta.u.aucBTPParams[0] = 0x00;
+        rBwcsPta.u.aucBTPParams[1] = 0x01;
+        rBwcsPta.u.aucBTPParams[2] = 0x00;
+        rBwcsPta.u.aucBTPParams[3] = 0x80;
+
+        wlanoidSetBT(prAdapter,
+            (PVOID)&rBwcsPta,
+            sizeof(PARAM_PTA_IPC_T),
+            &u4SetInfoLen);
+#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
+        nicReleaseAdapterMemory(prAdapter);
+    }
+
+    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) */
+        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) {
+                    break;
+                }
+                else {
+                    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 */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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
+*/
+/*----------------------------------------------------------------------------*/
+BOOL
+wlanISR (
+    IN P_ADAPTER_T prAdapter,
+    IN BOOLEAN fgGlobalIntrCtrl
+    )
+{
+    ASSERT(prAdapter);
+
+    if (fgGlobalIntrCtrl) {
+        nicDisableInterrupt(prAdapter);
+
+        //wlanIST(prAdapter);
+    }
+
+    return TRUE;
+}
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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);
+
+    ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter);
+
+    nicProcessIST(prAdapter);
+
+    nicEnableInterrupt(prAdapter);
+
+    RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE);
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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();
+
+    ASSERT(prAdapter);
+    ASSERT(prCmdQue);
+
+    prTempCmdQue = &rTempCmdQue;
+    prMergeCmdQue = &rMergeCmdQue;
+    prStandInCmdQue = &rStandInCmdQue;
+
+    QUEUE_INITIALIZE(prTempCmdQue);
+    QUEUE_INITIALIZE(prMergeCmdQue);
+    QUEUE_INITIALIZE(prStandInCmdQue);
+
+    //4 <1> Move whole list of CMD_INFO to temp queue
+    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
+    QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T);
+    while(prQueueEntry) {
+        prCmdInfo = (P_CMD_INFO_T)prQueueEntry;
+
+        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) {
+            wlanReleaseCommand(prAdapter, prCmdInfo);
+        }
+        else if(eFrameAction == FRAME_ACTION_QUEUE_PKT) {
+            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);
+                break;
+            }
+            else if(rStatus == WLAN_STATUS_PENDING) {
+                // command packet which needs further handling upon 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 {
+                P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T)prQueueEntry;
+
+                if (rStatus == WLAN_STATUS_SUCCESS) {
+                    if (prCmdInfo->pfCmdDoneHandler) {
+                        prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prCmdInfo->pucInfoBuffer);
+                    }
+                }
+                else {
+                    if (prCmdInfo->fgIsOid) {
+                        kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, prCmdInfo->u4SetInfoLen, rStatus);
+                    }
+                }
+
+                cmdBufFreeCmdInfo(prAdapter, prCmdInfo);
+            }
+        }
+        else {
+            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);
+    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 informations 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;
+
+    ASSERT(prAdapter);
+    ASSERT(prCmdInfo);
+    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;
+
+            // <1.2> Check if pending packet or resource was exhausted
+            if ((rStatus = nicTxAcquireResource(prAdapter, ucTC)) == 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) {
+                HAL_MCR_WR(prAdapter,
+                        (prCmdAccessReg->u4Address & BITS(2,31)), //address is in DWORD unit
+                        prCmdAccessReg->u4Data);
+            }
+            else {
+                P_CMD_ACCESS_REG prEventAccessReg;
+                UINT_32 u4Address;
+
+                u4Address = prCmdAccessReg->u4Address;
+                prEventAccessReg = (P_CMD_ACCESS_REG)prCmdInfo->pucInfoBuffer;
+                prEventAccessReg->u4Address = u4Address;
+
+                HAL_MCR_RD(prAdapter,
+                       prEventAccessReg->u4Address & BITS(2,31), //address is in DWORD unit
+                       &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) {
+            kalOidComplete(prAdapter->prGlueInfo,
+                    prCmdInfo->fgSetQuery,
+                    prCmdInfo->u4SetInfoLen,
+                    WLAN_STATUS_FAILURE);
+        }
+        break;
+
+    case COMMAND_TYPE_SECURITY_FRAME:
+        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:
+        ASSERT(0);
+        break;
+    }
+
+    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 UINT_32      u4Data
+    )
+{
+    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(INIT, ERROR, ("OID Timeout! Releasing pending OIDs ..\n"));
+
+    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;
+
+            if (prCmdInfo->fgIsOid) {
+                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);
+
+        // 2: Clear pending OID in glue layer command queue
+        kalOidCmdClearance(prAdapter->prGlueInfo);
+
+        // 3: Clear pending OID queued in pvOidEntry with REQ_FLAG_OID set
+        kalOidClearance(prAdapter->prGlueInfo);
+
+    } while(FALSE);
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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);
+
+    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);
+
+    return;
+} /* 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);
+
+    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)) {
+        }
+#endif
+    }
+
+    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;
+    }
+    nicRxReturnRFB(prAdapter, prSwRfb);
+}
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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
+    if (prAdapter->u4PsCurrentMeasureEn &&
+        (prAdapter->prGlueInfo->eParamMediaStateIndicated == PARAM_MEDIA_STATE_CONNECTED)) {
+        return WLAN_STATUS_SUCCESS; // note: return WLAN_STATUS_FAILURE or WLAN_STATUS_SUCCESS for blocking OIDs during current measurement ??
+    }
+
+#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
+    if (prAdapter->u4PsCurrentMeasureEn &&
+        (prAdapter->prGlueInfo->eParamMediaStateIndicated == PARAM_MEDIA_STATE_CONNECTED)) {
+        return WLAN_STATUS_SUCCESS; // note: return WLAN_STATUS_FAILURE or WLAN_STATUS_SUCCESS for blocking OIDs during current measurement ??
+    }
+
+#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) == WLAN_STATUS_RESOURCES) {
+            if (nicTxPollingResource(prAdapter, ucTC) != WLAN_STATUS_SUCCESS) {
+                DBGLOG(INIT, ERROR,("Fail to get TX resource return within timeout\n"));
+                status = WLAN_STATUS_FAILURE;
+                break;
+            }
+            else {
+                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) == 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 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
+    )
+{
+    #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;
+
+    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) == 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;
+            }
+            else {
+                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;
+
+    #elif defined(MT5931)
+
+    UINT_32 i, u4Value;
+    P_HIF_HW_TX_HEADER_T prHifTxHeader;
+
+    WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS;
+
+    ASSERT(prAdapter);
+    ASSERT(pucImgSecBuf);
+    ASSERT(u4ImgSecSize <= CMD_PKT_SIZE_FOR_IMAGE);
+
+    DEBUGFUNC("wlanImageSectionDownload");
+    DBGLOG(INIT, TRACE, ("Destination: 0x%08X / Length: 0x%08X\n", u4DestAddr, u4ImgSecSize));
+
+    if (u4ImgSecSize == 0) {
+        return WLAN_STATUS_SUCCESS;
+    }
+
+    // 1. Use TX coalescing buffer
+    prHifTxHeader = (P_HIF_HW_TX_HEADER_T) prAdapter->pucCoalescingBufCached;
+
+    // 2. Setup HIF_TX_HEADER
+    prHifTxHeader->u2TxByteCount = (UINT_16)(ALIGN_4(sizeof(HIF_HW_TX_HEADER_T) + u4ImgSecSize));
+    prHifTxHeader->ucEtherTypeOffset = 0;
+    prHifTxHeader->ucCSflags = 0;
+
+    // 3. Copy payload
+    kalMemCopy(prHifTxHeader->aucBuffer, pucImgSecBuf, u4ImgSecSize);
+
+    // 3.1 add 4-bytes zero tail
+    kalMemZero(&(prHifTxHeader->aucBuffer[ALIGN_4(u4ImgSecSize)]), sizeof(HIF_HW_TX_HEADER_T));
+
+    // 4. Poll til FWDL_RDY = 1
+    i = 0;
+    while(1) {
+        HAL_MCR_RD(prAdapter, MCR_FWDLSR, &u4Value);
+
+        if (u4Value & FWDLSR_FWDL_RDY) {
+            DBGLOG(INIT, TRACE, ("FWDL_RDY detected\n"));
+            break;
+        }
+        else if(kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE
+                || fgIsBusAccessFailed == TRUE) {
+            u4Status = WLAN_STATUS_FAILURE;
+            break;
+        }
+        else if(i >= CFG_RESPONSE_POLLING_TIMEOUT) {
+            DBGLOG(INIT, ERROR, ("Waiting for FWDL_RDY: Timeout (0x%08X)\n", u4Value));
+            u4Status = WLAN_STATUS_FAILURE;
+            break;
+        }
+        else {
+            i++;
+            kalMsleep(10);
+        }
+    }
+
+    // 5. Send firmware
+    HAL_PORT_WR(prAdapter,
+            MCR_FWDLDR,
+            prHifTxHeader->u2TxByteCount,
+            (PUINT_8)prHifTxHeader,
+            prAdapter->u4CoalescingBufCachedSize);
+
+    return u4Status;
+
+    #endif
+}
+
+#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) == 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;
+            }
+            else {
+                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;
+                       DBGLOG(INIT, ERROR, ("Bus error(%d)/Card removed(%d)\n", fgIsBusAccessFailed, kalIsCardRemoved(prAdapter->prGlueInfo)));
+        }
+        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;
+                       DBGLOG(INIT, ERROR, ("No RX response\n"));
+        }
+        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;
+                               DBGLOG(INIT, ERROR, ("EVENT-ID Mismatch: %d\n", prInitHifRxHeader->rInitWifiEvent.ucEID));
+            }
+            else if(prInitHifRxHeader->rInitWifiEvent.ucSeqNum != ucCmdSeqNum) {
+                u4Status = WLAN_STATUS_FAILURE;
+                               DBGLOG(INIT, ERROR, ("SEQ-NUM Mismatch: %d (expected: %d)\n", prInitHifRxHeader->rInitWifiEvent.ucSeqNum, ucCmdSeqNum));
+            }
+            else {
+                prEventPendingError = (P_INIT_EVENT_PENDING_ERROR) (prInitHifRxHeader->rInitWifiEvent.aucBuffer);
+                if(prEventPendingError->ucStatus != 0) { // 0 for download success
+                    u4Status = WLAN_STATUS_FAILURE;
+                                       DBGLOG(INIT, ERROR, ("ERROR CODE: %d\n", prEventCmdResult->ucStatus));
+                }
+                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) {
+            u4Status = WLAN_STATUS_FAILURE;
+                       DBGLOG(INIT, ERROR, ("Bus error(%d)/Card removed(%d)\n", fgIsBusAccessFailed, kalIsCardRemoved(prAdapter->prGlueInfo)));
+        }
+        else if(nicRxWaitResponse(prAdapter,
+                    0,
+                    aucBuffer,
+                    sizeof(INIT_HIF_RX_HEADER_T) + sizeof(INIT_EVENT_CMD_RESULT),
+                    &u4RxPktLength) != WLAN_STATUS_SUCCESS) {
+            u4Status = WLAN_STATUS_FAILURE;
+                       DBGLOG(INIT, ERROR, ("No RX response\n"));
+        }
+        else {
+            prInitHifRxHeader = (P_INIT_HIF_RX_HEADER_T) aucBuffer;
+
+            // EID / SeqNum check
+            if(prInitHifRxHeader->rInitWifiEvent.ucEID != INIT_EVENT_ID_CMD_RESULT) {
+                u4Status = WLAN_STATUS_FAILURE;
+                               DBGLOG(INIT, ERROR, ("EVENT-ID Mismatch: %d\n", prInitHifRxHeader->rInitWifiEvent.ucEID));
+            }
+            else if(prInitHifRxHeader->rInitWifiEvent.ucSeqNum != ucCmdSeqNum) {
+                u4Status = WLAN_STATUS_FAILURE;
+                               DBGLOG(INIT, ERROR, ("SEQ-NUM Mismatch: %d\n", prInitHifRxHeader->rInitWifiEvent.ucSeqNum));
+            }
+            else {
+                prEventCmdResult = (P_INIT_EVENT_CMD_RESULT) (prInitHifRxHeader->rInitWifiEvent.aucBuffer);
+                if(prEventCmdResult->ucStatus != 0) { // 0 for download success
+                    u4Status = WLAN_STATUS_FAILURE;
+                                       DBGLOG(INIT, ERROR, ("ERROR CODE: %d\n", prEventCmdResult->ucStatus));
+                }
+                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, 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) == 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;
+            }
+            else {
+                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
+*/
+/*----------------------------------------------------------------------------*/
+UINT_32 wlanCRC32(
+    PUINT_8 buf,
+    UINT_32 len)
+{
+    UINT_32 i, crc32 = 0xFFFFFFFF;
+    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 };
+
+    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:
+            nicRxProcessPktWithoutReorder(prAdapter, prSwRfb);
+            break;
+
+        case RX_PKT_DESTINATION_FORWARD:
+            nicRxProcessForwardPkt(prAdapter, prSwRfb);
+            break;
+
+        case RX_PKT_DESTINATION_HOST_WITH_FORWARD:
+            nicRxProcessGOBroadcastPkt(prAdapter, prSwRfb);
+            break;
+
+        case RX_PKT_DESTINATION_NULL:
+            nicRxReturnRFB(prAdapter, prSwRfb);
+            break;
+
+        default:
+            break;
+        }
+
+#if CFG_HIF_RX_STARVATION_WARNING
+        prRxCtrl->u4DequeuedCnt++;
+#endif
+        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);
+
+    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 set up the MCUSYS's OSC stable time
+*
+* @param prAdapter          Pointer to the Adapter structure.
+*
+* @return none
+*/
+/*----------------------------------------------------------------------------*/
+
+#if CFG_SUPPORT_OSC_SETTING && defined(MT5931)
+WLAN_STATUS
+wlanSetMcuOscStableTime (
+    IN P_ADAPTER_T      prAdapter,
+    IN UINT_16          u2OscStableTime
+    )
+{
+    UINT_8                  ucCmdSeqNum = 0;
+    P_CMD_INFO_T            prCmdInfo = NULL;
+    P_WIFI_CMD_T            prWifiCmd = NULL;
+    P_CMD_MCU_LP_PARAM_T    prMcuSetOscCmd = NULL;
+    WLAN_STATUS             status = WLAN_STATUS_SUCCESS;
+
+    ASSERT(prAdapter);
+
+    prCmdInfo = cmdBufAllocateCmdInfo(prAdapter,
+            CMD_HDR_SIZE + sizeof(CMD_MCU_LP_PARAM_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_MCU_LP_PARAM_T cmd pkt
+    prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL;
+    prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_MCU_LP_PARAM_T);
+    prCmdInfo->pfCmdDoneHandler = NULL;
+    prCmdInfo->pfCmdTimeoutHandler = NULL;
+    prCmdInfo->fgIsOid = FALSE;
+    prCmdInfo->ucCID = CMD_ID_SET_OSC;
+    prCmdInfo->fgSetQuery = TRUE;
+    prCmdInfo->fgNeedResp = FALSE;
+    prCmdInfo->fgDriverDomainMCR = FALSE;
+    prCmdInfo->ucCmdSeqNum = ucCmdSeqNum;
+    prCmdInfo->u4SetInfoLen = sizeof(CMD_MCU_LP_PARAM_T);
+
+    // 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_MCU_LP_PARAM_T
+    prMcuSetOscCmd = (P_CMD_MCU_LP_PARAM_T)(prWifiCmd->aucBuffer);
+    prMcuSetOscCmd->u2OscStableTime = u2OscStableTime;
+
+    status = wlanSendCommand(prAdapter, prCmdInfo);
+    cmdBufFreeCmdInfo(prAdapter, prCmdInfo);
+
+    return status;
+}
+#endif
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @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;
+    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;
+        }
+        else {
+#if CFG_SHOW_MACADDR_SOURCE
+            DBGLOG(INIT, INFO, ("Using dynamically generated MAC address"));
+#endif
+            // dynamic generate
+            u4SysTime = (UINT_32) 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
+    }
+
+    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
+
+    if(wlanSendCommand(prAdapter, prCmdInfo) == WLAN_STATUS_RESOURCES) {
+        prCmdInfo->pfCmdDoneHandler = nicCmdEventQueryAddress;
+        kalEnqueueCommand(prAdapter->prGlueInfo, (P_QUE_ENTRY_T)prCmdInfo);
+
+        return WLAN_STATUS_PENDING;
+    }
+    else {
+        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;
+
+    ASSERT(prAdapter);
+    ASSERT(prPacket);
+
+    if (kalQoSFrameClassifierAndPacketInfo(prAdapter->prGlueInfo,
+                prPacket,
+                &ucPriorityParam,
+                &u4PacketLen,
+                aucEthDestAddr,
+                &fgIs1x,
+                &fgIsPAL,
+                &ucNetworkType) == TRUE) {
+        if(fgIs1x == FALSE) {
+            return FALSE;
+        }
+        else {
+            KAL_SPIN_LOCK_DECLARATION();
+            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);
+
+            DBGLOG(RSN, INFO, ("T1X len=%d\n", u4PacketLen));
+
+            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;
+#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;
+
+                kalEnqueueCommand(prAdapter->prGlueInfo, (P_QUE_ENTRY_T)prCmdInfo);
+
+                return TRUE;
+            }
+            else {
+                ASSERT(0);
+                return FALSE;
+            }
+        }
+    }
+    else {
+        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) {
+        P_STA_RECORD_T prSta = cnmGetStaRecByIndex(prAdapter, prCmdInfo->ucStaRecIndex);
+        if (prSta) {
+            kalMsleep(10);
+            secFsmEventEapolTxDone(prAdapter, prSta, TX_RESULT_SUCCESS);
+        }
+    }
+
+    kalSecurityFrameSendComplete(prAdapter->prGlueInfo,
+            prCmdInfo->prPacket,
+            WLAN_STATUS_SUCCESS);
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @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);
+
+    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
+    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;
+    }
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @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 scanning result
+    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 -
+                    (((UINT_32)pucIEPtr) + u4IELength - ((UINT_32)(&(prAdapter->rWlanInfo.aucScanIEBuf[0]))));
+
+                kalMemCopy(pucIEPtr,
+                        (PUINT_8)(((UINT_32)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)((UINT_32)(prAdapter->rWlanInfo.apucScanResultIEs[j]) - u4IELength);
+                    }
+                }
+            }
+        }
+
+        i++;
+    }
+
+    return;
+}
+
+
+#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
+    return;
+}
+
+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);
+
+    return;
+}
+#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;
+
+    wlanSendCommand(prAdapter, prCmdInfo);
+    cmdBufFreeCmdInfo(prAdapter, prCmdInfo);
+
+    if(nicRxWaitResponse(prAdapter,
+                1,
+                aucBuffer,
+                sizeof(WIFI_EVENT_T) + sizeof(EVENT_BASIC_CONFIG),
+                &u4RxPktLength) != WLAN_STATUS_SUCCESS) {
+        return WLAN_STATUS_FAILURE;
+    }
+
+    // header checking ..
+    prHifRxHdr = (P_HIF_RX_HEADER_T)aucBuffer;
+    if(prHifRxHdr->u2PacketType != 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_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;
+
+    wlanSendCommand(prAdapter, prCmdInfo);
+    cmdBufFreeCmdInfo(prAdapter, prCmdInfo);
+
+    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_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;
+
+
+#if CFG_ENABLE_CAL_LOG
+    DBGLOG(INIT, INFO, (" RF CAL FAIL  = (%d),BB CAL FAIL  = (%d)\n",
+            prEventNicCapability->ucRfCalFail ,prEventNicCapability->ucBbCalFail ));
+#endif
+    return WLAN_STATUS_SUCCESS;
+}
+
+#ifdef 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] .u4TxpowerOffset;
+        }
+    }
+
+
+    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_STRUC_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_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_STRUC_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
+
+#ifdef 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)));
+        }
+    }
+
+    /* 3. Check if needs to support 5GHz */
+    if(prRegInfo->ucEnable5GBand) {
+        // check if it is disabled by hardware
+        if(prAdapter->fgIsHw5GBandDisabled
+                || prRegInfo->ucSupport5GBand == 0) {
+            prAdapter->fgEnable5GBand = FALSE;
+        }
+        else {
+            prAdapter->fgEnable5GBand = TRUE;
+        }
+    }
+    else {
+        prAdapter->fgEnable5GBand = FALSE;
+    }
+
+    /* 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));
+
+#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);
+
+    /* 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;
+
+        wlanSendSetQueryCmd(prAdapter,
+                CMD_ID_SET_EDGE_TXPWR_LIMIT,
+                TRUE,
+                FALSE,
+                FALSE,
+                NULL,
+                NULL,
+                sizeof(CMD_EDGE_TXPWR_LIMIT_T),
+                (PUINT_8)&rCmdEdgeTxPwrLimit,
+                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);
+
+    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++) {
+       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;
+
+    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;
+    }
+    else {
+        prMsduInfo->eSrc = TX_PACKET_OS;
+
+        if(nicTxFillMsduInfo(prAdapter,
+                    prMsduInfo,
+                    prNativePacket) == FALSE) { // packet is not extractable
+            kalSendComplete(prAdapter->prGlueInfo,
+                    prNativePacket,
+                    WLAN_STATUS_INVALID_PACKET);
+
+            nicTxReturnMsduInfo(prAdapter, prMsduInfo);
+
+            return WLAN_STATUS_INVALID_PACKET;
+        }
+        else {
+            // 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 packet by txDequeuTxPackets()
+    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 packets
+            nicTxMsduInfoList(prAdapter, prMsduInfo);
+
+            // <4> update TC by txAdjustTcQuotas()
+            nicTxAdjustTcq(prAdapter);
+        }
+        else {
+            wlanProcessQueuedMsduInfo(prAdapter, prMsduInfo);
+        }
+    }
+
+#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);
+
+    ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter);
+
+    /* Reset sleepy state */
+    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);
+
+    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;
+
+    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;
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @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);
+    }
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @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
+            || (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));
+
+        // 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) {
+        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)((UINT_32)(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) {
+        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(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)((UINT_32)(prBeacon) + WLAN_MAC_MGMT_HEADER_LEN));
+        }
+    }
+#endif
+
+    if(fgGenErrMsg == TRUE) {
+        cnmMemFree(prAdapter, prBeacon);
+    }
+
+    return WLAN_STATUS_SUCCESS;
+}
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/common/wlan_oid.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/common/wlan_oid.c
new file mode 100755 (executable)
index 0000000..25a13a7
--- /dev/null
@@ -0,0 +1,10787 @@
+/*
+** $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 $
+**
+** 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 occured 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 continous memory demands
+ * separate kalMemAlloc() into virtually-continous and physically-continous 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 availble 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
+ * upate 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 occured
+ *
+ * 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 managment 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 <stddef.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 DBG
+extern UINT_8  aucDebugModule[DBG_MODULE_NUM];
+extern UINT_32 u4DebugModule;
+UINT_32 u4DebugModuleTemp;
+#endif /* DBG */
+
+/******************************************************************************
+*                           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
+*******************************************************************************
+*/
+extern int sprintf(char * buf, const char * fmt, ...);
+
+/******************************************************************************
+*                              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(REQ, TRACE, ("NDIS supported network type list: %ld\n",
+        prSupported->NumberOfItems));
+    DBGLOG_MEM8(REQ, INFO, 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(REQ, 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(REQ,
+        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(REQ, INFO, ("Not support network type: %d\n", eNewNetworkType));
+        rStatus = WLAN_STATUS_NOT_SUPPORTED;
+        break;
+
+    default:
+        DBGLOG(REQ, 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(REQ, 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(REQ, 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;
+
+    DEBUGFUNC("wlanoidSetBssidListScan()");
+
+    if (prAdapter->rAcpiState == ACPI_STATE_D3) {
+        DBGLOG(REQ, 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(REQ, WARN, ("Return from BSSID list scan! (radio off). ACPI=D%d, Radio=%d\n",
+                    prAdapter->rAcpiState, prAdapter->fgIsRadioOff));
+        return WLAN_STATUS_SUCCESS;
+    }
+
+    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
+#endif
+    {
+        if(prAdapter->fgEnOnlineScan == TRUE) {
+            aisFsmScanRequest(prAdapter, prSsid, NULL, 0);
+        }
+        else if(kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_CONNECTED) {
+            aisFsmScanRequest(prAdapter, prSsid, NULL, 0);
+        }
+    }
+
+    return WLAN_STATUS_SUCCESS;
+} /* 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_PARAM_SSID_T prSsid;
+    PUINT_8 pucIe;
+    UINT_32 u4IeLength;
+
+    DEBUGFUNC("wlanoidSetBssidListScanExt()");
+
+    if (prAdapter->rAcpiState == ACPI_STATE_D3) {
+        DBGLOG(REQ, 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(u4SetBufferLen != sizeof(PARAM_SCAN_REQUEST_EXT_T)) {
+        return WLAN_STATUS_INVALID_LENGTH;
+    }
+
+    if (prAdapter->fgIsRadioOff) {
+        DBGLOG(REQ, WARN, ("Return from BSSID list scan! (radio off). ACPI=D%d, Radio=%d\n",
+                    prAdapter->rAcpiState, prAdapter->fgIsRadioOff));
+        return WLAN_STATUS_SUCCESS;
+    }
+
+    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;
+    }
+
+#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
+#endif
+    {
+        if(prAdapter->fgEnOnlineScan == TRUE) {
+            aisFsmScanRequest(prAdapter, prSsid, pucIe, u4IeLength);
+        }
+        else if(kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_CONNECTED) {
+            aisFsmScanRequest(prAdapter, prSsid, pucIe, u4IeLength);
+        }
+    }
+
+    return WLAN_STATUS_SUCCESS;
+} /* 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;
+
+    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(REQ, 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);
+        }
+        else {
+            kalIndicateStatusAndComplete(prGlueInfo,
+                    WLAN_STATUS_MEDIA_DISCONNECT,
+                    NULL,
+                    0);
+        }
+    }
+
+    // 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 = DISCONNECT_REASON_CODE_NEW_CONNECTION;
+
+    if (EQUAL_MAC_ADDR(prAdapter->rWifiVar.rConnSettings.aucBSSID, pAddr)) {
+        prAisAbortMsg->fgDelayIndication = TRUE;
+    }
+    else {
+        /* 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);
+        prAisAbortMsg->fgDelayIndication = FALSE;
+    }
+
+    mboxSendMsg(prAdapter,
+            MBOX_ID_0,
+            (P_MSG_HDR_T) prAisAbortMsg,
+            MSG_SEND_METHOD_BUF);
+
+    return WLAN_STATUS_SUCCESS;
+} /* end of wlanoidSetBssid() */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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(REQ, 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 {
+            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;
+
+    if (EQUAL_SSID(prAdapter->rWifiVar.rConnSettings.aucSSID,
+                prAdapter->rWifiVar.rConnSettings.ucSSIDLen,
+                pParamSsid->aucSsid,
+                pParamSsid->u4SsidLen)) {
+        prAisAbortMsg->fgDelayIndication = TRUE;
+    }
+    else {
+        /* Update the information to CONNECTION_SETTINGS_T */
+        COPY_SSID(prAdapter->rWifiVar.rConnSettings.aucSSID,
+                prAdapter->rWifiVar.rConnSettings.ucSSIDLen,
+                pParamSsid->aucSsid,
+                (UINT_8)pParamSsid->u4SsidLen);
+
+        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(REQ, WARN, ("Invalid length %lu\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(REQ, 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(REQ, INFO, ("IBSS mode\n"));
+             break;
+        case NET_TYPE_INFRA:
+             DBGLOG(REQ, INFO, ("Infrastructure mode\n"));
+             break;
+        default:
+             DBGLOG(REQ, 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(REQ, 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(REQ, 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(REQ, 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(REQ, INFO, ("Current auth mode: Open\n"));
+        break;
+
+    case AUTH_MODE_SHARED:
+        DBGLOG(REQ, INFO, ("Current auth mode: Shared\n"));
+        break;
+
+    case AUTH_MODE_AUTO_SWITCH:
+        DBGLOG(REQ, INFO, ("Current auth mode: Auto-switch\n"));
+        break;
+
+    case AUTH_MODE_WPA:
+        DBGLOG(REQ, INFO, ("Current auth mode: WPA\n"));
+        break;
+
+    case AUTH_MODE_WPA_PSK:
+        DBGLOG(REQ, INFO, ("Current auth mode: WPA PSK\n"));
+        break;
+
+    case AUTH_MODE_WPA_NONE:
+        DBGLOG(REQ, INFO, ("Current auth mode: WPA None\n"));
+        break;
+
+    case AUTH_MODE_WPA2:
+        DBGLOG(REQ, INFO, ("Current auth mode: WPA2\n"));
+        break;
+
+    case AUTH_MODE_WPA2_PSK:
+        DBGLOG(REQ, INFO, ("Current auth mode: WPA2 PSK\n"));
+        break;
+
+    default:
+        DBGLOG(REQ, INFO, ("Current auth mode: %d\n",
+            *(P_ENUM_PARAM_AUTH_MODE_T)pvQueryBuffer));
+    }
+#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(REQ, 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(REQ, 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:
+        ;
+    }
+
+    /* 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(REQ, INFO, ("Current privacy mode: open mode\n"));
+        break;
+
+    case PRIVACY_FILTER_8021xWEP:
+        DBGLOG(REQ, INFO, ("Current privacy mode: filtering mode\n"));
+        break;
+
+    default:
+        DBGLOG(REQ, 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(REQ, 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(REQ, 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(REQ, 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;
+        prAdapter->rWifiVar.rConnSettings.eEncStatus = ENUM_ENCRYPTION1_KEY_ABSENT;//ENUM_ENCRYPTION_DISABLED;
+        {
+            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(INIT, 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(REQ, 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(REQ, 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(REQ, 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(REQ, 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(REQ, 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(REQ, 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(REQ, INFO, ("Set: Dump PARAM_KEY_INDEX content\n"));
+    DBGLOG(REQ, INFO, ("Index : 0x%08lx\n", u4KeyId));
+
+    if (prAdapter->rAcpiState == ACPI_STATE_D3) {
+        DBGLOG(REQ, 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(REQ, ERROR, ("Invalid WEP key index: 0x%08lx\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(REQ, ERROR, ("invalid WEP key ID %lu\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,
+    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;
+
+    DEBUGFUNC("wlanoidSetAddKey");
+    DBGLOG(REQ, LOUD, ("\n"));
+
+    ASSERT(prAdapter);
+    ASSERT(pvSetBuffer);
+    ASSERT(pu4SetInfoLen);
+
+    if (prAdapter->rAcpiState == ACPI_STATE_D3) {
+        DBGLOG(REQ, 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(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 */
+    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 */
+    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;
+
+    /* Dump PARAM_KEY content. */
+    DBGLOG(REQ, TRACE, ("Set: Dump PARAM_KEY content\n"));
+    DBGLOG(REQ, TRACE, ("Length    : 0x%08lx\n", prNewKey->u4Length));
+    DBGLOG(REQ, TRACE, ("Key Index : 0x%08lx\n", prNewKey->u4KeyIndex));
+    DBGLOG(REQ, TRACE, ("Key Length: 0x%08lx\n", prNewKey->u4KeyLength));
+    DBGLOG(REQ, TRACE, ("BSSID:\n"));
+    DBGLOG_MEM8(REQ, TRACE, prNewKey->arBSSID, sizeof(PARAM_MAC_ADDRESS));
+    DBGLOG(REQ, TRACE, ("Key RSC:\n"));
+    DBGLOG_MEM8(REQ, TRACE, &prNewKey->rKeyRSC, sizeof(PARAM_KEY_RSC));
+    DBGLOG(REQ, TRACE, ("Key Material:\n"));
+    DBGLOG_MEM8(REQ, 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 */
+    }
+
+    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(INIT, ERROR, ("Allocate CMD_INFO_T ==> FAILED.\n"));
+        return WLAN_STATUS_FAILURE;
+    }
+
+    // increase command sequence number
+    ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter);
+    DBGLOG(REQ, INFO, ("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 = 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 */
+
+    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 (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;
+        }
+    }
+    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 {
+            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));
+            }
+            prCmdKey->ucAlgorithmId = CIPHER_SUITE_TKIP;
+        }
+    }
+
+    // insert into prCmdQueue
+    kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T)prCmdInfo);
+
+    // wakeup txServiceThread later
+    GLUE_SET_EVENT(prGlueInfo);
+
+    return WLAN_STATUS_PENDING;
+} /* 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(REQ, 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(REQ, INFO, ("Set: Dump PARAM_REMOVE_KEY content\n"));
+    DBGLOG(REQ, INFO, ("Length    : 0x%08lx\n", prRemovedKey->u4Length));
+    DBGLOG(REQ, INFO, ("Key Index : 0x%08lx\n", prRemovedKey->u4KeyIndex));
+    DBGLOG(REQ, INFO, ("BSSID:\n"));
+    DBGLOG_MEM8(REQ, INFO, 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(REQ, ERROR, ("invalid key index: 0x%08lx\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%08lx\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(INIT, 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;
+        }
+        else {
+            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(REQ, ERROR, ("Unknown Encryption Status Setting:%d\n",
+            prAdapter->rWifiVar.rConnSettings.eEncStatus));
+    }
+
+#if DBG
+    DBGLOG(REQ, 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(REQ, 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(REQ, 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;
+    }
+
+    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(REQ, TRACE, ("Test - Type %ld\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;
+        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(REQ, INFO, ("Count %lu\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 "MACSTR" idx=%d PMKID value "MACSTR"\n",
+                MAC2STR(prAisSpecBssInfo->arPmkidCache[j].rBssidInfo.arBSSID),j,  MAC2STR(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(REQ, WARN, ("Invalid length %ld\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(REQ, WARN, ("Invalid length %ld\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(REQ, WARN, ("Invalid length %ld\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(REQ, 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(REQ, WARN, ("Too short length %ld\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(REQ, WARN, ("Too short length %ld\n", u4QueryBufferLen));
+        return WLAN_STATUS_BUFFER_TOO_SHORT;
+    }
+
+    *(PARAM_RSSI *) pvQueryBuffer = prAdapter->rWlanInfo.rRssiTriggerValue;
+    DBGLOG(REQ, INFO, ("RSSI trigger: %ld 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(REQ, LOUD, ("\n"));
+
+    ASSERT(prAdapter);
+    if (u4QueryBufferLen) {
+        ASSERT(pvQueryBuffer);
+    }
+    ASSERT(pu4QueryInfoLen);
+
+    if (prAdapter->rAcpiState == ACPI_STATE_D3) {
+        DBGLOG(REQ, 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;
+    }
+    else
+#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(REQ, LOUD, ("\n"));
+
+    ASSERT(prAdapter);
+    if (u4QueryBufferLen) {
+        ASSERT(pvQueryBuffer);
+    }
+    ASSERT(pu4QueryInfoLen);
+
+    if (prAdapter->rAcpiState == ACPI_STATE_D3) {
+        DBGLOG(REQ, 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;
+    }
+    else
+#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(REQ, LOUD, ("\n"));
+
+    ASSERT(prAdapter);
+    if (u4QueryBufferLen) {
+        ASSERT(pvQueryBuffer);
+    }
+    ASSERT(pu4QueryInfoLen);
+
+    if (prAdapter->rAcpiState == ACPI_STATE_D3) {
+        DBGLOG(REQ, 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;
+    }
+    else
+#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
+wlanoidQueryStatistics (
+    IN  P_ADAPTER_T       prAdapter,
+    IN  PVOID             pvQueryBuffer,
+    IN  UINT_32           u4QueryBufferLen,
+    OUT PUINT_32          pu4QueryInfoLen
+    )
+{
+    DEBUGFUNC("wlanoidQueryStatistics");
+    DBGLOG(REQ, 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(REQ, 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(REQ, WARN, ("Too short length %ld\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;
+    }
+    else
+#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(REQ, WARN, ("Invalid length %ld\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(REQ, WARN, ("Invalid length %ld\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(INIT, 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(INIT, 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) {
+        *(PUINT_32)pvQueryBuffer = 10000; // change to unit of 100bps
+        return WLAN_STATUS_SUCCESS;
+    }
+    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_STRUC_T prMcrRdInfo;
+    CMD_ACCESS_REG rCmdAccessReg;
+
+    DEBUGFUNC("wlanoidQueryMcrRead");
+    DBGLOG(INIT, LOUD,("\n"));
+
+    ASSERT(prAdapter);
+    ASSERT(pu4QueryInfoLen);
+    if (u4QueryBufferLen) {
+        ASSERT(pvQueryBuffer);
+    }
+
+    *pu4QueryInfoLen = sizeof(PARAM_CUSTOM_MCR_RW_STRUC_T);
+
+    if (u4QueryBufferLen < sizeof(PARAM_CUSTOM_MCR_RW_STRUC_T)) {
+        return WLAN_STATUS_INVALID_LENGTH;
+    }
+
+    prMcrRdInfo = (P_PARAM_CUSTOM_MCR_RW_STRUC_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(INIT, TRACE, ("MCR Read: Offset = %#08lx, Data = %#08lx\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_STRUC_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(INIT, LOUD,("\n"));
+
+    ASSERT(prAdapter);
+    ASSERT(pu4SetInfoLen);
+
+    *pu4SetInfoLen = sizeof(PARAM_CUSTOM_MCR_RW_STRUC_T);
+
+    if (u4SetBufferLen < sizeof(PARAM_CUSTOM_MCR_RW_STRUC_T)) {
+        return WLAN_STATUS_INVALID_LENGTH;
+    }
+
+    ASSERT(pvSetBuffer);
+
+    prMcrWrInfo = (P_PARAM_CUSTOM_MCR_RW_STRUC_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(INIT, 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(INIT, 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(INIT, TRACE, ("MCR Write: Offset = %#08lx, Data = %#08lx\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_STRUC_T prSwCtrlInfo;
+    WLAN_STATUS rWlanStatus;
+    UINT_16 u2Id, u2SubId;
+    UINT_32 u4Data;
+
+    CMD_SW_DBG_CTRL_T rCmdSwCtrl;
+
+    DEBUGFUNC("wlanoidQuerySwCtrlRead");
+    DBGLOG(INIT, LOUD,("\n"));
+
+    ASSERT(prAdapter);
+    ASSERT(pu4QueryInfoLen);
+    if (u4QueryBufferLen) {
+        ASSERT(pvQueryBuffer);
+    }
+
+    *pu4QueryInfoLen = sizeof(PARAM_CUSTOM_SW_CTRL_STRUC_T);
+
+    if (u4QueryBufferLen < sizeof(PARAM_CUSTOM_SW_CTRL_STRUC_T)) {
+        return WLAN_STATUS_INVALID_LENGTH;
+    }
+
+    prSwCtrlInfo = (P_PARAM_CUSTOM_SW_CTRL_STRUC_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_STRUC_T prSwCtrlInfo;
+    CMD_SW_DBG_CTRL_T rCmdSwCtrl;
+    WLAN_STATUS rWlanStatus;
+    UINT_16 u2Id, u2SubId;
+    UINT_32 u4Data;
+
+    DEBUGFUNC("wlanoidSetSwCtrlWrite");
+    DBGLOG(INIT, LOUD,("\n"));
+
+    ASSERT(prAdapter);
+    ASSERT(pu4SetInfoLen);
+
+    *pu4SetInfoLen = sizeof(PARAM_CUSTOM_SW_CTRL_STRUC_T);
+
+    if (u4SetBufferLen < sizeof(PARAM_CUSTOM_SW_CTRL_STRUC_T)) {
+        return WLAN_STATUS_INVALID_LENGTH;
+    }
+
+    ASSERT(pvSetBuffer);
+
+    prSwCtrlInfo = (P_PARAM_CUSTOM_SW_CTRL_STRUC_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;
+                }
+
+                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;
+            }
+
+
+            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, INFO, ("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, INFO, ("set smt fixed rate: %d \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
+                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
+                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,
+                        nicCmdEventSetCommon,
+                        nicOidCmdTimeoutCommon,
+                        sizeof(CMD_ACCESS_REG),
+                        (PUINT_8)&rCmdAccessReg,
+                        pvSetBuffer,
+                        0
+                        );
+
+                // 4. Disable Roaming
+                rCmdSwCtrl.u4Id = 0x90000204;
+                rCmdSwCtrl.u4Data = 0x0;
+                wlanSendSetQueryCmd(prAdapter,
+                        CMD_ID_SW_DBG_CTRL,
+                        TRUE,
+                        FALSE,
+                        FALSE,
+                        nicCmdEventSetCommon,
+                        nicOidCmdTimeoutCommon,
+                        sizeof(CMD_SW_DBG_CTRL_T),
+                        (PUINT_8)&rCmdSwCtrl,
+                        pvSetBuffer,
+                        u4SetBufferLen
+                        );
+
+                rCmdSwCtrl.u4Id = 0x90000200;
+                rCmdSwCtrl.u4Data = 0x820000;
+                wlanSendSetQueryCmd(prAdapter,
+                        CMD_ID_SW_DBG_CTRL,
+                        TRUE,
+                        FALSE,
+                        FALSE,
+                        nicCmdEventSetCommon,
+                        nicOidCmdTimeoutCommon,
+                        sizeof(CMD_SW_DBG_CTRL_T),
+                        (PUINT_8)&rCmdSwCtrl,
+                        pvSetBuffer,
+                        u4SetBufferLen
+                        );
+
+                // Disalbe auto tx power
+                //
+                rCmdSwCtrl.u4Id = 0xa0100003;
+                rCmdSwCtrl.u4Data = 0x0;
+                wlanSendSetQueryCmd(prAdapter,
+                        CMD_ID_SW_DBG_CTRL,
+                        TRUE,
+                        FALSE,
+                        FALSE,
+                        nicCmdEventSetCommon,
+                        nicOidCmdTimeoutCommon,
+                        sizeof(CMD_SW_DBG_CTRL_T),
+                        (PUINT_8)&rCmdSwCtrl,
+                        pvSetBuffer,
+                        u4SetBufferLen
+                        );
+
+
+
+                // 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,
+                        TRUE);
+                }
+
+                // 5. Disable Beacon Timeout Detection
+                prAdapter->fgDisBcnLostDetection = TRUE;
+            }
+            else if (u2SubId == 0x1235) {
+
+                // 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,
+                        nicCmdEventSetCommon,
+                        nicOidCmdTimeoutCommon,
+                        sizeof(CMD_ACCESS_REG),
+                        (PUINT_8)&rCmdAccessReg,
+                        pvSetBuffer,
+                        0
+                        );
+
+                // 4. Enable Roaming
+                rCmdSwCtrl.u4Id = 0x90000204;
+                rCmdSwCtrl.u4Data = 0x1;
+                wlanSendSetQueryCmd(prAdapter,
+                        CMD_ID_SW_DBG_CTRL,
+                        TRUE,
+                        FALSE,
+                        FALSE,
+                        nicCmdEventSetCommon,
+                        nicOidCmdTimeoutCommon,
+                        sizeof(CMD_SW_DBG_CTRL_T),
+                        (PUINT_8)&rCmdSwCtrl,
+                        pvSetBuffer,
+                        u4SetBufferLen
+                        );
+
+                rCmdSwCtrl.u4Id = 0x90000200;
+                rCmdSwCtrl.u4Data = 0x820000;
+                wlanSendSetQueryCmd(prAdapter,
+                        CMD_ID_SW_DBG_CTRL,
+                        TRUE,
+                        FALSE,
+                        FALSE,
+                        nicCmdEventSetCommon,
+                        nicOidCmdTimeoutCommon,
+                        sizeof(CMD_SW_DBG_CTRL_T),
+                        (PUINT_8)&rCmdSwCtrl,
+                        pvSetBuffer,
+                        u4SetBufferLen
+                        );
+
+                // Enable auto tx power
+                //
+
+                rCmdSwCtrl.u4Id = 0xa0100003;
+                rCmdSwCtrl.u4Data = 0x1;
+                wlanSendSetQueryCmd(prAdapter,
+                        CMD_ID_SW_DBG_CTRL,
+                        TRUE,
+                        FALSE,
+                        FALSE,
+                        nicCmdEventSetCommon,
+                        nicOidCmdTimeoutCommon,
+                        sizeof(CMD_SW_DBG_CTRL_T),
+                        (PUINT_8)&rCmdSwCtrl,
+                        pvSetBuffer,
+                        u4SetBufferLen
+                        );
+
+
+                // 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,
+                        TRUE);
+                }
+
+                // 5. Enable Beacon Timeout Detection
+                prAdapter->fgDisBcnLostDetection = FALSE;
+            }
+#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_STRUC_T prEepromRwInfo;
+    CMD_ACCESS_EEPROM rCmdAccessEeprom;
+
+    DEBUGFUNC("wlanoidQueryEepromRead");
+
+    ASSERT(prAdapter);
+    ASSERT(pu4QueryInfoLen);
+    if (u4QueryBufferLen) {
+        ASSERT(pvQueryBuffer);
+    }
+
+    *pu4QueryInfoLen = sizeof(PARAM_CUSTOM_EEPROM_RW_STRUC_T);
+
+    if (u4QueryBufferLen < sizeof(PARAM_CUSTOM_EEPROM_RW_STRUC_T)) {
+        return WLAN_STATUS_INVALID_LENGTH;
+    }
+
+    prEepromRwInfo = (P_PARAM_CUSTOM_EEPROM_RW_STRUC_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_STRUC_T prEepromRwInfo;
+    CMD_ACCESS_EEPROM rCmdAccessEeprom;
+
+    DEBUGFUNC("wlanoidSetEepromWrite");
+    DBGLOG(INIT, LOUD,("\n"));
+
+    ASSERT(prAdapter);
+    ASSERT(pu4SetInfoLen);
+
+    *pu4SetInfoLen = sizeof(PARAM_CUSTOM_EEPROM_RW_STRUC_T);
+
+    if (u4SetBufferLen < sizeof(PARAM_CUSTOM_EEPROM_RW_STRUC_T)) {
+        return WLAN_STATUS_INVALID_LENGTH;
+    }
+
+    ASSERT(pvSetBuffer);
+
+    prEepromRwInfo = (P_PARAM_CUSTOM_EEPROM_RW_STRUC_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(REQ, LOUD, ("\n"));
+
+    ASSERT(prAdapter);
+    if (u4QueryBufferLen) {
+        ASSERT(pvQueryBuffer);
+    }
+    ASSERT(pu4QueryInfoLen);
+
+    if (prAdapter->rAcpiState == ACPI_STATE_D3) {
+        DBGLOG(REQ, 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;
+    }
+    else
+#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(REQ, LOUD, ("\n"));
+
+    ASSERT(prAdapter);
+    if (u4QueryBufferLen) {
+        ASSERT(pvQueryBuffer);
+    }
+    ASSERT(pu4QueryInfoLen);
+
+    if (prAdapter->rAcpiState == ACPI_STATE_D3) {
+        DBGLOG(REQ, 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;
+    }
+    else
+#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(REQ, LOUD, ("\n"));
+
+    ASSERT(prAdapter);
+    if (u4QueryBufferLen) {
+        ASSERT(pvQueryBuffer);
+    }
+    ASSERT(pu4QueryInfoLen);
+
+    if (prAdapter->rAcpiState == ACPI_STATE_D3) {
+        DBGLOG(REQ, 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;
+    }
+    else
+#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(REQ, LOUD, ("\n"));
+
+    ASSERT(prAdapter);
+    if (u4QueryBufferLen) {
+        ASSERT(pvQueryBuffer);
+    }
+    ASSERT(pu4QueryInfoLen);
+
+    if (prAdapter->rAcpiState == ACPI_STATE_D3) {
+        DBGLOG(REQ, 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;
+    }
+    else
+#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(REQ, LOUD, ("\n"));
+
+    ASSERT(prAdapter);
+    if (u4QueryBufferLen) {
+        ASSERT(pvQueryBuffer);
+    }
+    ASSERT(pu4QueryInfoLen);
+
+    if (prAdapter->rAcpiState == ACPI_STATE_D3) {
+        DBGLOG(REQ, 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;
+    }
+    else
+#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(REQ, LOUD, ("\n"));
+
+    ASSERT(prAdapter);
+    if (u4QueryBufferLen) {
+        ASSERT(pvQueryBuffer);
+    }
+    ASSERT(pu4QueryInfoLen);
+
+    if (prAdapter->rAcpiState == ACPI_STATE_D3) {
+        DBGLOG(REQ, 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;
+    }
+    else
+#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(REQ, WARN, ("Custom OID interface version: %#08lX\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(REQ, WARN, ("Invalid MC list length %ld\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 = 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;
+
+    DEBUGFUNC("wlanoidSetCurrentPacketFilter");
+
+    ASSERT(prAdapter);
+    ASSERT(pu4SetInfoLen);
+
+    if (u4SetBufferLen < sizeof(UINT_32)) {
+        *pu4SetInfoLen = sizeof(UINT_32);
+        return WLAN_STATUS_INVALID_LENGTH;
+    }
+    ASSERT(pvSetBuffer);
+
+    /* Set the new packet filter. */
+    u4NewPacketFilter = *(PUINT_32) pvSetBuffer;
+
+    DBGLOG(REQ, INFO, ("New packet filter: %#08lx\n", u4NewPacketFilter));
+
+    if (prAdapter->rAcpiState == ACPI_STATE_D3) {
+        DBGLOG(REQ, 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(REQ, INFO, ("Enable promiscuous mode\n"));
+        }
+        else {
+            DBGLOG(REQ, INFO, ("Disable promiscuous mode\n"));
+        }
+
+        if (u4NewPacketFilter & PARAM_PACKET_FILTER_ALL_MULTICAST) {
+            DBGLOG(REQ, INFO, ("Enable all-multicast mode\n"));
+        }
+        else if (u4NewPacketFilter & PARAM_PACKET_FILTER_MULTICAST) {
+            DBGLOG(REQ, INFO, ("Enable multicast\n"));
+        }
+        else {
+            DBGLOG(REQ, INFO, ("Disable multicast\n"));
+        }
+
+        if (u4NewPacketFilter & PARAM_PACKET_FILTER_BROADCAST) {
+            DBGLOG(REQ, INFO, ("Enable Broadcast\n"));
+        }
+        else {
+            DBGLOG(REQ, INFO, ("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(REQ, INFO, ("Query Power State: D0\n"));
+        break;
+    case ParamDeviceStateD1:
+        DBGLOG(REQ, INFO, ("Query Power State: D1\n"));
+        break;
+    case ParamDeviceStateD2:
+        DBGLOG(REQ, INFO, ("Query Power State: D2\n"));
+        break;
+    case ParamDeviceStateD3:
+        DBGLOG(REQ, 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(REQ, INFO, ("Set Power State: D0\n"));
+        kalDevSetPowerState(prAdapter->prGlueInfo, (UINT_32)ParamDeviceStateD0);
+        fgRetValue = nicpmSetAcpiPowerD0(prAdapter);
+        break;
+    case ParamDeviceStateD1:
+        DBGLOG(REQ, INFO, ("Set Power State: D1\n"));
+        /* no break here */
+    case ParamDeviceStateD2:
+        DBGLOG(REQ, INFO, ("Set Power State: D2\n"));
+        /* no break here */
+    case ParamDeviceStateD3:
+        DBGLOG(REQ, 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(REQ, 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(REQ, 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(REQ, WARN, ("Invalid length %ld\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(REQ, 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) {
+        kalIndicateStatusAndComplete(prAdapter->prGlueInfo,
+                WLAN_STATUS_MEDIA_DISCONNECT,
+                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(REQ, WARN, ("Invalid length %ld\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(INIT, INFO, ("Set Wi-Fi PS mode to CAM (%d)\n", ePowerMode));
+        break;
+    case Param_PowerModeMAX_PSP:
+        DBGLOG(INIT, INFO, ("Set Wi-Fi PS mode to MAX PS (%d)\n", ePowerMode));
+        break;
+    case Param_PowerModeFast_PSP:
+        DBGLOG(INIT, INFO, ("Set Wi-Fi PS mode to FAST PS (%d)\n", ePowerMode));
+        break;
+    default:
+        DBGLOG(INIT, 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(REQ, TRACE, ("Invalid Beacon Interval = %ld\n", *pu4BeaconInterval));
+        return WLAN_STATUS_INVALID_DATA;
+    }
+
+    prAdapter->rWlanInfo.u2BeaconPeriod = (UINT_16)*pu4BeaconInterval;
+
+    DBGLOG(REQ, 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(INIT, 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;
+
+    DEBUGFUNC("wlanoidSetNetworkAddress");
+    DBGLOG(INIT, 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) ((UINT_32) prNetworkAddress +
+            (UINT_32) (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_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(REQ, INFO, ("u4IpAddressCount (%d)\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(REQ, INFO, ("prNetAddrIp->in_addr:%d:%d:%d:%d\n", pucBuf[0], pucBuf[1],pucBuf[2],pucBuf[3]));
+            }
+
+            prNetworkAddress = (P_PARAM_NETWORK_ADDRESS) ((UINT_32) prNetworkAddress +
+                (UINT_32) (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,
+                    FALSE,
+                    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;
+    }
+
+    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;
+    }
+
+    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_STRUC_T  prRfATInfo;
+    WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+
+    DEBUGFUNC("wlanoidRftestQueryAutoTest");
+
+    ASSERT(prAdapter);
+    if (u4QueryBufferLen) {
+        ASSERT(pvQueryBuffer);
+    }
+    ASSERT(pu4QueryInfoLen);
+
+    *pu4QueryInfoLen = sizeof(PARAM_MTK_WIFI_TEST_STRUC_T);
+
+    if (u4QueryBufferLen != sizeof(PARAM_MTK_WIFI_TEST_STRUC_T)) {
+        DBGLOG(REQ, ERROR, ("Invalid data. QueryBufferLen: %ld.\n",
+                    u4QueryBufferLen));
+        return WLAN_STATUS_INVALID_LENGTH;
+    }
+
+    prRfATInfo = (P_PARAM_MTK_WIFI_TEST_STRUC_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_STRUC_T  prRfATInfo;
+    WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+
+    DEBUGFUNC("wlanoidRftestSetAutoTest");
+
+    ASSERT(prAdapter);
+    ASSERT(pvSetBuffer);
+    ASSERT(pu4SetInfoLen);
+
+    *pu4SetInfoLen = sizeof(PARAM_MTK_WIFI_TEST_STRUC_T);
+
+    if (u4SetBufferLen != sizeof(PARAM_MTK_WIFI_TEST_STRUC_T)) {
+        DBGLOG(REQ, ERROR, ("Invalid data. SetBufferLen: %ld.\n",
+                    u4SetBufferLen));
+        return WLAN_STATUS_INVALID_LENGTH;
+    }
+
+    prRfATInfo = (P_PARAM_MTK_WIFI_TEST_STRUC_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(INIT, 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;
+    }
+    else {
+        prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + sizeof(CMD_TEST_CTRL_T)));
+
+        if (!prCmdInfo) {
+            DBGLOG(INIT, 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(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_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(REQ, 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(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_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(REQ, LOUD, ("\r\n"));
+
+    if (u4SetBufferLen < 20 /* From EID to Group cipher */) {
+        prAdapter->rWifiVar.rConnSettings.fgWapiMode = FALSE;
+        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, TRACE, ("Not WAPI IE ?! u4SetBufferLen = %d\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 += 2;
+    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 %ld\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(REQ, LOUD, ("\r\n"));
+
+    ASSERT(prAdapter);
+    ASSERT(pvSetBuffer);
+    ASSERT(pu4SetInfoLen);
+
+    if (prAdapter->rAcpiState == ACPI_STATE_D3) {
+        DBGLOG(REQ, 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(REQ, 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(REQ, TRACE, ("Set: Dump P_PARAM_WPI_KEY_T content\r\n"));
+    DBGLOG(REQ, TRACE, ("TYPE      : %d\r\n", prNewKey->eKeyType));
+    DBGLOG(REQ, TRACE, ("Direction : %d\r\n", prNewKey->eDirection));
+    DBGLOG(REQ, TRACE, ("KeyID     : %d\r\n", prNewKey->ucKeyID));
+    DBGLOG(REQ, TRACE, ("AddressIndex:\r\n"));
+    DBGLOG_MEM8(REQ, TRACE, prNewKey->aucAddrIndex, 12);
+    prNewKey->u4LenWPIEK = 16;
+
+    DBGLOG_MEM8(REQ, TRACE, (PUINT_8)prNewKey->aucWPIEK, (UINT_8)prNewKey->u4LenWPIEK);
+    prNewKey->u4LenWPICK = 16;
+
+    DBGLOG(REQ, TRACE, ("CK Key(%d):\r\n", (UINT_8)prNewKey->u4LenWPICK));
+    DBGLOG_MEM8(REQ, TRACE, (PUINT_8)prNewKey->aucWPICK, (UINT_8)prNewKey->u4LenWPICK);
+    DBGLOG(REQ, 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(REQ, TRACE, (PUINT_8)prNewKey->aucPN, 16);
+
+    prGlueInfo = prAdapter->prGlueInfo;
+
+    prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + u4SetBufferLen));
+
+    if (!prCmdInfo) {
+        DBGLOG(INIT, 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(REQ, 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 %ld\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(REQ, 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(REQ, 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(REQ, 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(REQ, 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_STRUC_T prWmmPsTestInfo;
+    WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+    CMD_SET_WMM_PS_TEST_STRUC_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_STRUC_T);
+
+    prWmmPsTestInfo = (P_PARAM_CUSTOM_WMM_PS_TEST_STRUC_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_STRUC_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_STRUC_T prMtkSltInfo = (P_PARAM_MTK_SLT_TEST_STRUC_T)NULL;
+    P_SLT_INFO_T prSltInfo = (P_SLT_INFO_T)NULL;
+
+    DEBUGFUNC("wlanoidQuerySLTStatus");
+    DBGLOG(REQ, LOUD, ("\r\n"));
+
+    ASSERT(prAdapter);
+    ASSERT(pu4QueryInfoLen);
+
+    *pu4QueryInfoLen = sizeof(PARAM_MTK_SLT_TEST_STRUC_T);
+
+    if (u4QueryBufferLen < sizeof(PARAM_MTK_SLT_TEST_STRUC_T)) {
+        return WLAN_STATUS_INVALID_LENGTH;
+    }
+
+    ASSERT(pvQueryBuffer);
+
+    prMtkSltInfo = (P_PARAM_MTK_SLT_TEST_STRUC_T)pvQueryBuffer;
+
+    prSltInfo = &(prAdapter->rWifiVar.rSltInfo);
+
+    switch (prMtkSltInfo->rSltFuncIdx) {
+    case ENUM_MTK_SLT_FUNC_LP_SET:
+        {
+            P_PARAM_MTK_SLT_LP_TEST_STRUC_T prLpSetting = (P_PARAM_MTK_SLT_LP_TEST_STRUC_T)NULL;
+
+            ASSERT(prMtkSltInfo->u4FuncInfoLen == sizeof(PARAM_MTK_SLT_LP_TEST_STRUC_T));
+
+            prLpSetting = (P_PARAM_MTK_SLT_LP_TEST_STRUC_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_STRUC_T prMtkSltInfo = (P_PARAM_MTK_SLT_TEST_STRUC_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(REQ, LOUD, ("\r\n"));
+
+    ASSERT(prAdapter);
+    ASSERT(pu4SetInfoLen);
+
+    *pu4SetInfoLen = sizeof(PARAM_MTK_SLT_TEST_STRUC_T);
+
+    if (u4SetBufferLen < sizeof(PARAM_MTK_SLT_TEST_STRUC_T)) {
+        return WLAN_STATUS_INVALID_LENGTH;
+    }
+
+    ASSERT(pvSetBuffer);
+
+    prMtkSltInfo = (P_PARAM_MTK_SLT_TEST_STRUC_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_STRUC_T prMtkSltInit = (P_PARAM_MTK_SLT_INITIAL_STRUC_T)NULL;
+
+            ASSERT(prMtkSltInfo->u4FuncInfoLen == sizeof(PARAM_MTK_SLT_INITIAL_STRUC_T));
+
+            prMtkSltInit = (P_PARAM_MTK_SLT_INITIAL_STRUC_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;
+                    }
+                    else {
+                        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;
+        }
+        else {
+            P_PARAM_MTK_SLT_TR_TEST_STRUC_T prTRSetting = (P_PARAM_MTK_SLT_TR_TEST_STRUC_T)NULL;
+
+            ASSERT(prMtkSltInfo->u4FuncInfoLen == sizeof(PARAM_MTK_SLT_TR_TEST_STRUC_T));
+
+            prStaRec = prSltInfo->prPseudoStaRec;
+            prTRSetting = (P_PARAM_MTK_SLT_TR_TEST_STRUC_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 */
+                prStaRec->u2HtCapInfo |= HT_CAP_INFO_SUP_CHNL_WIDTH;   /* It would controls RFBW capability in WTBL. */
+                prStaRec->ucDesiredPhyTypeSet = PHY_TYPE_BIT_HT;               /* This controls RF BW, RF BW would be 40 only if
+                                                                                                                 * 1. PHY_TYPE_BIT_HT is TRUE.
+                                                                                                                 * 2. SCO is SCA/SCB.
+                                                                                                                 */
+
+                /* 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 {
+                        if (prBssInfo->ucPrimaryChannel <5) {
+                            prBssInfo->ucPrimaryChannel = 8;   // For channel 1, testing L20 at channel 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 {
+                        if (prBssInfo->ucPrimaryChannel > 10) {
+                            prBssInfo->ucPrimaryChannel = 3;  // For channel 11 / 14. testing U20 at channel 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_STRUC_T prLpSetting = (P_PARAM_MTK_SLT_LP_TEST_STRUC_T)NULL;
+
+            ASSERT(prMtkSltInfo->u4FuncInfoLen == sizeof(PARAM_MTK_SLT_LP_TEST_STRUC_T));
+
+            prLpSetting = (P_PARAM_MTK_SLT_LP_TEST_STRUC_T)&prMtkSltInfo->unFuncInfoContent;
+
+            if (prSltInfo->prPseudoBssDesc == NULL) {
+                /* Please initial SLT Mode first. */
+                break;
+            }
+            else {
+                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) {
+        fgStatus = kalCfgDataRead16(prAdapter->prGlueInfo,
+                prNvramRwInfo->ucEepromIndex << 1, /* change to byte offset */
+                &u2Data);
+
+        if(fgStatus) {
+            prNvramRwInfo->u2EepromData = u2Data;
+            DBGLOG(REQ, INFO, ("NVRAM Read: index=%#X, data=%#02X\r\n",
+                        prNvramRwInfo->ucEepromIndex, u2Data));
+        }
+        else{
+            DBGLOG(REQ, 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(REQ, INFO, ("EEPROM size =%d\r\n", prNvramRwInfo->u2EepromData));
+    }
+
+    *pu4QueryInfoLen = sizeof(PARAM_CUSTOM_EEPROM_RW_STRUC_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(INIT, 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;
+
+    fgStatus = kalCfgDataWrite16(prAdapter->prGlueInfo,
+            prNvramRwInfo->ucEepromIndex << 1, /* change to byte offset */
+            prNvramRwInfo->u2EepromData
+            );
+
+    if(fgStatus == FALSE){
+        DBGLOG(REQ, 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;
+
+    ASSERT(prAdapter);
+    ASSERT(pvSetBuffer);
+    ASSERT(u4SetBufferLen == 2);
+
+    *pu4SetInfoLen = 2;
+
+    pucCountry = pvSetBuffer;
+
+    prAdapter->rWifiVar.rConnSettings.u2CountryCode =
+        (((UINT_16) pucCountry[0]) << 8) | ((UINT_16) pucCountry[1]) ;
+
+    prAdapter->prDomainInfo = NULL; /* Force to re-search country code */
+    rlmDomainSendCmd(prAdapter, TRUE);
+
+    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_STRUC_T prNoaParam;
+    CMD_CUSTOM_NOA_PARAM_STRUC_T rCmdNoaParam;
+
+    DEBUGFUNC("wlanoidSetNoaParam");
+    DBGLOG(INIT, LOUD,("\n"));
+
+    ASSERT(prAdapter);
+    ASSERT(pu4SetInfoLen);
+
+    *pu4SetInfoLen = sizeof(PARAM_CUSTOM_NOA_PARAM_STRUC_T);
+
+    if (u4SetBufferLen < sizeof(PARAM_CUSTOM_NOA_PARAM_STRUC_T)) {
+        return WLAN_STATUS_INVALID_LENGTH;
+    }
+
+    ASSERT(pvSetBuffer);
+
+    prNoaParam = (P_PARAM_CUSTOM_NOA_PARAM_STRUC_T)pvSetBuffer;
+
+    kalMemZero(&rCmdNoaParam, sizeof(CMD_CUSTOM_NOA_PARAM_STRUC_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_STRUC_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_STRUC_T prOppPsParam;
+    CMD_CUSTOM_OPPPS_PARAM_STRUC_T rCmdOppPsParam;
+
+    DEBUGFUNC("wlanoidSetOppPsParam");
+    DBGLOG(INIT, LOUD,("\n"));
+
+    ASSERT(prAdapter);
+    ASSERT(pu4SetInfoLen);
+
+    *pu4SetInfoLen = sizeof(PARAM_CUSTOM_OPPPS_PARAM_STRUC_T);
+
+    if (u4SetBufferLen < sizeof(PARAM_CUSTOM_OPPPS_PARAM_STRUC_T)) {
+        return WLAN_STATUS_INVALID_LENGTH;
+    }
+
+    ASSERT(pvSetBuffer);
+
+    prOppPsParam = (P_PARAM_CUSTOM_OPPPS_PARAM_STRUC_T)pvSetBuffer;
+
+    kalMemZero(&rCmdOppPsParam, sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUC_T));
+    rCmdOppPsParam.u4CTwindowMs = prOppPsParam->u4CTwindowMs;
+
+    return wlanSendSetQueryCmd(prAdapter,
+            CMD_ID_SET_OPPPS_PARAM,
+            TRUE,
+            FALSE,
+            TRUE,
+            nicCmdEventSetCommon,
+            nicOidCmdTimeoutCommon,
+            sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUC_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_STRUC_T prUapsdParam;
+    CMD_CUSTOM_UAPSD_PARAM_STRUC_T rCmdUapsdParam;
+    P_PM_PROFILE_SETUP_INFO_T prPmProfSetupInfo;
+    P_BSS_INFO_T prBssInfo;
+
+
+    DEBUGFUNC("wlanoidSetUApsdParam");
+    DBGLOG(INIT, LOUD,("\n"));
+
+    ASSERT(prAdapter);
+    ASSERT(pu4SetInfoLen);
+
+    *pu4SetInfoLen = sizeof(PARAM_CUSTOM_UAPSD_PARAM_STRUC_T);
+
+    if (u4SetBufferLen < sizeof(PARAM_CUSTOM_UAPSD_PARAM_STRUC_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_STRUC_T)pvSetBuffer;
+
+    kalMemZero(&rCmdUapsdParam, sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUC_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_STRUC_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 %ld\n", u4SetBufferLen));
+        return WLAN_STATUS_INVALID_LENGTH;
+    }
+
+    if (prAdapter->rAcpiState == ACPI_STATE_D3) {
+        DBGLOG(REQ, 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
+    printk(KERN_INFO DRV_NAME "BCM BWCS CMD: BWCS CMD = %02x%02x%02x%02x\n",
+            prPtaIpc->u.aucBTPParams[0], prPtaIpc->u.aucBTPParams[1], prPtaIpc->u.aucBTPParams[2], prPtaIpc->u.aucBTPParams[3]);
+
+    printk(KERN_INFO DRV_NAME "BCM BWCS CMD: aucBTPParams[0] = %02x, aucBTPParams[1] = %02x, aucBTPParams[2] = %02x, aucBTPParams[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(REQ, WARN, ("Invalid length %lu\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(REQ, WARN, ("Invalid length %lu\n", u4QueryBufferLen));
+        return WLAN_STATUS_INVALID_LENGTH;
+    }
+
+    ASSERT(pvQueryBuffer);
+
+    prPtaInfo = &prAdapter->rPtaInfo;
+    pu4SingleAntenna = (PUINT_32)pvQueryBuffer;
+
+    if(prPtaInfo->fgSingleAntenna) {
+        //printk(KERN_WARNING DRV_NAME"Q Single Ant = 1\r\n");
+        *pu4SingleAntenna = 1;
+    } else {
+        //printk(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(REQ, 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) {
+        //printk(KERN_WARNING DRV_NAME"Set Single Ant = 0\r\n");
+        prPtaInfo->fgSingleAntenna = FALSE;
+    } else {
+        //printk(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(REQ, WARN, ("Invalid length %lu\n", u4QueryBufferLen));
+        return WLAN_STATUS_INVALID_LENGTH;
+    }
+
+    ASSERT(pvQueryBuffer);
+
+    prPtaInfo = &prAdapter->rPtaInfo;
+    pu4Pta = (PUINT_32)pvQueryBuffer;
+
+    if(prPtaInfo->fgEnabled) {
+        //printk(KERN_WARNING DRV_NAME"PTA = 1\r\n");
+        *pu4Pta = 1;
+    } else {
+        //printk(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(REQ, 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) {
+        //printk(KERN_WARNING DRV_NAME"Set Pta= 0\r\n");
+        nicPtaSetFunc(prAdapter, FALSE);
+    } else {
+        //printk(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(REQ, LOUD, ("\r\n"));
+
+    ASSERT(prAdapter);
+    ASSERT(pvSetBuffer);
+
+#if 0
+    printk("c2GLegacyStaPwrOffset=%d\n", pTxPwr->c2GLegacyStaPwrOffset);
+    printk("c2GHotspotPwrOffset=%d\n", pTxPwr->c2GHotspotPwrOffset);
+    printk("c2GP2pPwrOffset=%d\n", pTxPwr->c2GP2pPwrOffset);
+    printk("c2GBowPwrOffset=%d\n", pTxPwr->c2GBowPwrOffset);
+    printk("c5GLegacyStaPwrOffset=%d\n", pTxPwr->c5GLegacyStaPwrOffset);
+    printk("c5GHotspotPwrOffset=%d\n", pTxPwr->c5GHotspotPwrOffset);
+    printk("c5GP2pPwrOffset=%d\n", pTxPwr->c5GP2pPwrOffset);
+    printk("c5GBowPwrOffset=%d\n", pTxPwr->c5GBowPwrOffset);
+    printk("ucConcurrencePolicy=%d\n", pTxPwr->ucConcurrencePolicy);
+
+    for (i=0; i<14;i++)
+        printk("acTxPwrLimit2G[%d]=%d\n", i, pTxPwr->acTxPwrLimit2G[i]);
+
+    for (i=0; i<4;i++)
+        printk("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_STRUC_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_STRUC_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(REQ, TRACE, ("[%d] 0x%X, len %d, remain len %d\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_STRUC_T prMemDumpInfo;
+
+    DEBUGFUNC("wlanoidQueryMemDump");
+    DBGLOG(INIT, LOUD,("\n"));
+
+    ASSERT(prAdapter);
+    ASSERT(pu4QueryInfoLen);
+    if (u4QueryBufferLen) {
+        ASSERT(pvQueryBuffer);
+    }
+
+    *pu4QueryInfoLen = sizeof(UINT_32);
+
+    prMemDumpInfo = (P_PARAM_CUSTOM_MEM_DUMP_STRUC_T)pvQueryBuffer;
+    DBGLOG(REQ, TRACE, ("Dump 0x%X, len %d\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;
+    P_PARAM_CUSTOM_P2P_SET_STRUC_T prSetP2P = (P_PARAM_CUSTOM_P2P_SET_STRUC_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_STRUC_T);
+    if (u4SetBufferLen < sizeof(PARAM_CUSTOM_P2P_SET_STRUC_T)) {
+        DBGLOG(REQ, WARN, ("Invalid length %ld\n", u4SetBufferLen));
+        return WLAN_STATUS_INVALID_LENGTH;
+    }
+
+    prSetP2P = (P_PARAM_CUSTOM_P2P_SET_STRUC_T) pvSetBuffer;
+
+    DBGLOG(P2P, INFO, ("Set P2P enable[%ld] mode[%ld]\n", 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 {
+        if (prAdapter->fgIsP2PRegistered) {
+            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
+
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/common/wlan_p2p.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/common/wlan_p2p.c
new file mode 100755 (executable)
index 0000000..be51207
--- /dev/null
@@ -0,0 +1,1811 @@
+/*
+** $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 Channle 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 continous memory demands
+ * separate kalMemAlloc() into virtually-continous and physically-continous 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"
+
+/******************************************************************************
+*                              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(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_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%08lx\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%08lx\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(INIT, 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) ((UINT_32) prNetworkAddress +
+            (UINT_32) (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) ((UINT_32) prNetworkAddress +
+            (UINT_32) (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 %ld\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_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(INIT, TRACE, ("\n"));
+    printk("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) ((UINT_32) prNetworkAddress +
+            (UINT_32) (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;
+
+        printk("u4IpAddressCount (%ld) \n", (INT_32)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;
+                printk("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) ((UINT_32) prNetworkAddress +
+                (UINT_32) (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 %ld\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);
+
+    return wlanoidSendSetQueryP2PCmd(prAdapter,
+            CMD_ID_MAC_MCAST_ADDR,
+            TRUE,
+            FALSE,
+            FALSE,              // This CMD response is no need to complete the OID. Or the event would unsync.
+            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
+    if ((ucVersionNum = p2pFuncGetVersionNumOfSD(prAdapter)) == 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
+    if ((ucVersionNum = p2pFuncGetVersionNumOfSD(prAdapter)) == 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_STRUC_T prNoaParam;
+    CMD_CUSTOM_NOA_PARAM_STRUC_T rCmdNoaParam;
+
+    DEBUGFUNC("wlanoidSetNoaParam");
+    DBGLOG(INIT, TRACE,("\n"));
+
+    ASSERT(prAdapter);
+    ASSERT(pu4SetInfoLen);
+
+    *pu4SetInfoLen = sizeof(PARAM_CUSTOM_NOA_PARAM_STRUC_T);
+
+    if (u4SetBufferLen < sizeof(PARAM_CUSTOM_NOA_PARAM_STRUC_T)) {
+        return WLAN_STATUS_INVALID_LENGTH;
+    }
+
+    ASSERT(pvSetBuffer);
+
+    prNoaParam = (P_PARAM_CUSTOM_NOA_PARAM_STRUC_T)pvSetBuffer;
+
+    kalMemZero(&rCmdNoaParam, sizeof(CMD_CUSTOM_NOA_PARAM_STRUC_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_STRUC_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_STRUC_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_STRUC_T prOppPsParam;
+    CMD_CUSTOM_OPPPS_PARAM_STRUC_T rCmdOppPsParam;
+
+    DEBUGFUNC("wlanoidSetOppPsParam");
+    DBGLOG(INIT, TRACE,("\n"));
+
+    ASSERT(prAdapter);
+    ASSERT(pu4SetInfoLen);
+
+    *pu4SetInfoLen = sizeof(PARAM_CUSTOM_OPPPS_PARAM_STRUC_T);
+
+    if (u4SetBufferLen < sizeof(PARAM_CUSTOM_OPPPS_PARAM_STRUC_T)) {
+        return WLAN_STATUS_INVALID_LENGTH;
+    }
+
+    ASSERT(pvSetBuffer);
+
+    prOppPsParam = (P_PARAM_CUSTOM_OPPPS_PARAM_STRUC_T)pvSetBuffer;
+
+    kalMemZero(&rCmdOppPsParam, sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUC_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_STRUC_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_STRUC_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_STRUC_T prUapsdParam;
+    CMD_CUSTOM_UAPSD_PARAM_STRUC_T rCmdUapsdParam;
+    P_PM_PROFILE_SETUP_INFO_T prPmProfSetupInfo;
+    P_BSS_INFO_T prBssInfo;
+
+
+    DEBUGFUNC("wlanoidSetUApsdParam");
+    DBGLOG(INIT, TRACE,("\n"));
+
+    ASSERT(prAdapter);
+    ASSERT(pu4SetInfoLen);
+
+    *pu4SetInfoLen = sizeof(PARAM_CUSTOM_UAPSD_PARAM_STRUC_T);
+
+    if (u4SetBufferLen < sizeof(PARAM_CUSTOM_UAPSD_PARAM_STRUC_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_STRUC_T)pvSetBuffer;
+
+    kalMemZero(&rCmdUapsdParam, sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUC_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_STRUC_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_STRUC_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 */
+
+#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 %ld\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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/CFG_Wifi_File.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/CFG_Wifi_File.h
new file mode 100755 (executable)
index 0000000..dd1fce8
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+** $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 */
+#if defined(MT6620)
+    INT_8       acReserved[3];
+#elif defined(MT5931) || 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;
+} 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              aucTailReserved[256-8];
+} 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_STRUC_INSPECTING_ASSERT
+#define DATA_STRUC_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.
+ */
+__KAL_INLINE__ VOID
+nvramOffsetCheck (
+    VOID
+    )
+{
+    DATA_STRUC_INSPECTING_ASSERT(
+        OFFSET_OF(WIFI_CFG_PARAM_STRUCT, u2Part2OwnVersion) == 256);
+
+    DATA_STRUC_INSPECTING_ASSERT(
+        sizeof(WIFI_CFG_PARAM_STRUCT) == 512);
+
+    DATA_STRUC_INSPECTING_ASSERT(
+        (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucEFUSE) & 0x0001) == 0);
+
+    DATA_STRUC_INSPECTING_ASSERT(
+        (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucRegSubbandInfo) & 0x0001) == 0);
+}
+#endif
+
+#endif /* _CFG_WIFI_FILE_H */
+
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/config.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/config.h
new file mode 100755 (executable)
index 0000000..d2943bf
--- /dev/null
@@ -0,0 +1,1525 @@
+/*
+** $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 paramters 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. Seperate 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 settting 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] Chnage 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 adress & 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 reponse 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
+********************************************************************************
+*/
+
+#ifndef MT6620
+#define MT6620
+#endif
+
+#ifdef MT5931
+#undef MT5931
+#endif
+
+#ifdef MT6628
+#undef MT6628
+#endif
+
+
+/*******************************************************************************
+*                              C O N S T A N T S
+********************************************************************************
+*/
+//2 Flags for OS capability
+
+#ifdef LINUX
+    #ifdef CONFIG_X86
+        #define MTK_WCN_HIF_SDIO        0
+    #else
+        #define MTK_WCN_HIF_SDIO        1
+    #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
+
+//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
+
+#define CFG_SUPPORT_802_11D             1 /*!< 1(default): Enable 802.11d
+                                                     0: Disable */
+
+#define CFG_SUPPORT_SPEC_MGMT       0   /* Spectrum Management (802.11h): TPC and DFS */
+#define CFG_SUPPORT_RRM             0   /* Radio Reasource Measurement (802.11k) */
+#define CFG_SUPPORT_QUIET           0   /* Quiet (802.11h) */
+
+
+#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 */
+
+/*------------------------------------------------------------------------------
+ * SLT Option
+ *------------------------------------------------------------------------------
+ */
+#define CFG_SLT_SUPPORT                             0
+
+
+#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   1
+#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: Suport 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(MT5931)
+
+#define CFG_MULTI_ECOVER_SUPPORT    0
+#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
+
+
+/*------------------------------------------------------------------------------
+ * 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
+
+/*------------------------------------------------------------------------------
+ * 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                      256
+
+/*! 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 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
+
+#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 */
+
+/*------------------------------------------------------------------------------
+ * 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 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                  1
+#else
+    #define CFG_IST_LOOP_COUNT                  1
+#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(MT6620) || defined(MT6628)
+    #define CFG_ENABLE_FW_DOWNLOAD_AGGREGATION  0
+    #define CFG_ENABLE_FW_DIVIDED_DOWNLOAD      1
+#else
+    #define CFG_ENABLE_FW_DOWNLOAD_AGGREGATION  0
+    #define CFG_ENABLE_FW_DIVIDED_DOWNLOAD      0
+#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(MT5931)
+    #define CFG_FW_LOAD_ADDRESS                     0xFF900000
+    #define CFG_FW_START_ADDRESS                    0x00000000
+#elif defined(MT6628)
+    #define CFG_FW_LOAD_ADDRESS                     0x00060000
+    #define CFG_OVERRIDE_FW_START_ADDRESS           0
+    #define CFG_FW_START_ADDRESS                    0x00060000
+#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
+
+/*------------------------------------------------------------------------------
+ * 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                       1
+#define CFG_SUPPORT_AAA                         1
+
+
+#if (defined(MT5931) && defined(LINUX))
+#define CFG_SUPPORT_BCM                         1
+#define CFG_SUPPORT_BCM_BWCS                    1
+#define CFG_SUPPORT_BCM_BWCS_DEBUG              1
+#else
+#define CFG_SUPPORT_BCM                         0
+#define CFG_SUPPORT_BCM_BWCS                    0
+#define CFG_SUPPORT_BCM_BWCS_DEBUG              0
+#endif
+
+#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
+
+#if defined(MT5931)
+#define CFG_SUPPORT_WHOLE_CHIP_RESET    1  /* for e3 chip only */
+#endif
+
+#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 bus error tolerance
+ *------------------------------------------------------------------------------
+ */
+#define CFG_FORCE_RESET_UNDER_BUS_ERROR     0
+
+
+/*******************************************************************************
+*                             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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/debug.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/debug.h
new file mode 100755 (executable)
index 0000000..3d5f03e
--- /dev/null
@@ -0,0 +1,517 @@
+/*
+** $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 catagory
+**  \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"
+#if CFG_SUPPORT_XLOG
+#include "linux/xlog.h"
+#endif
+
+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_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          "%02x:%02x:%02x:%02x:%02x:%02x"
+
+/* Debug print argument for the MAC Address */
+#define MAC2STR(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 " = " MACSTR "\n", MAC2STR(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.
+ */
+#define LOG_FUNC_TIME           kalPrint
+#define LOG_FUNC                kalPrint
+
+#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(__FUNCTION__)
+        #define DEBUGFUNC(_Func)
+    #else
+        #define DEBUGFUNC(_Func) static const char __FUNCTION__[] = _Func;
+    #endif
+
+    /* The following macros are used for future debug message. */
+    /* TODO(Kevin): We should remove INITLOG/ERRORLOG/WARNLOG macro sooner or later */
+    #define INITLOG(_Fmt) \
+    { \
+        if (aucDebugModule[DBG_INIT_IDX] & DBG_CLASS_TRACE) { \
+            LOG_FUNC("%s: ", __FUNCTION__); \
+            LOG_FUNC _Fmt; \
+        } \
+    }
+
+    #define ERRORLOG(_Fmt) \
+    { \
+        if (aucDebugModule[DBG_INIT_IDX] & DBG_CLASS_ERROR) { \
+            LOG_FUNC("**Error[%s:%d]-", __FILE__, __LINE__); \
+            LOG_FUNC _Fmt; \
+        } \
+    }
+
+    #define WARNLOG(_Fmt) \
+    { \
+        if (aucDebugModule[DBG_INIT_IDX] & DBG_CLASS_WARN) { \
+            LOG_FUNC("**Warning[%s:%d]-", __FILE__, __LINE__); \
+            LOG_FUNC _Fmt; \
+        } \
+    }
+
+    /*lint -save -e960 Multiple use of '#/##' */
+    #define DBGLOG(_Module, _Class, _Fmt) \
+        { \
+            if (aucDebugModule[DBG_##_Module##_IDX] & DBG_CLASS_##_Class) { \
+                if (DBG_CLASS_##_Class == DBG_CLASS_ERROR) { \
+                    LOG_FUNC_TIME("**Error[%s:%d]-", __FILE__, __LINE__); \
+                    LOG_FUNC("%s: (" #_Module " " #_Class ") ", __FUNCTION__); \
+                } \
+                else if (DBG_CLASS_##_Class == DBG_CLASS_WARN) { \
+                    LOG_FUNC_TIME("**Warning[%s:%d]-", __FILE__, __LINE__); \
+                    LOG_FUNC("%s: (" #_Module " " #_Class ") ", __FUNCTION__); \
+                } \
+                else if (DBG_CLASS_##_Class == DBG_CLASS_EVENT) { \
+                } \
+                else { \
+                    LOG_FUNC_TIME("%s: (" #_Module " " #_Class ") ", __FUNCTION__); \
+                } \
+                LOG_FUNC _Fmt; \
+            } \
+        }
+
+    #define DBGLOG_MEM8(_Module, _Class, _StartAddr, _Length) \
+        { \
+            if (aucDebugModule[DBG_##_Module##_IDX] & DBG_CLASS_##_Class) { \
+                LOG_FUNC("%s: (" #_Module " " #_Class ")\n", __FUNCTION__); \
+                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", __FUNCTION__); \
+                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)
+
+#if defined(LINUX)
+    #define DBGLOG(_Module, _Class, _Fmt) \
+    { \
+        _Module##_##_Class##_LOGFUNC _Fmt; \
+    }
+#else
+    #define DBGLOG(_Module, _Class, _Fmt)
+#endif
+
+#if CFG_SUPPORT_XLOG
+    #define DBGLOG_MEM8(_Module, _Class, _StartAddr, _Length) \
+    { \
+        _Module##_##_Class##_LOGFUNC (__FUNCTION__);\
+        _Module##_##_Class##_LOGDUMP8(_StartAddr, _Length); \
+    }
+#else
+    #define DBGLOG_MEM8(_Module, _Class, _StartAddr, _Length)
+#endif
+    #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)
+    #define ASSERT_REPORT(_exp, _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_STRUC_INSPECTING_ASSERT
+#define DATA_STRUC_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
+********************************************************************************
+*/
+#if DBG
+VOID
+dumpMemory8 (
+    IN PUINT_8 pucStartAddr,
+    IN UINT_32 u4Length
+    );
+
+VOID
+dumpMemory32 (
+    IN PUINT_32 pu4StartAddr,
+    IN UINT_32  u4Length
+    );
+#elif CFG_SUPPORT_XLOG
+VOID
+dumpMemory8 (
+    IN UINT_32  log_level,
+    IN PUINT_8 pucStartAddr,
+    IN UINT_32 u4Length
+    );
+#endif /* DBG */
+
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+#endif /* _DEBUG_H */
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/link.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/link.h
new file mode 100755 (executable)
index 0000000..deefb03
--- /dev/null
@@ -0,0 +1,414 @@
+/*
+** $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
+********************************************************************************
+*/
+#define INVALID_LINK_POISON1    ((VOID *) 0x00100101) // May cause page fault & unalignment issue (data abort)
+#define INVALID_LINK_POISON2    ((VOID *) 0x00100201) // Used to verify that nonbody uses non-initialized link entries.
+
+
+/*******************************************************************************
+*                             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)
+*/
+/*----------------------------------------------------------------------------*/
+__KAL_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;
+
+    return;
+} /* 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)
+*/
+/*----------------------------------------------------------------------------*/
+__KAL_INLINE__ VOID
+linkAdd (
+    IN P_LINK_ENTRY_T prNew,
+    IN P_LINK_T prLink
+    )
+{
+    __linkAdd(prNew, (P_LINK_ENTRY_T)prLink, prLink->prNext);
+
+    return;
+} /* 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)
+*/
+/*----------------------------------------------------------------------------*/
+__KAL_INLINE__ VOID
+linkAddTail (
+    IN P_LINK_ENTRY_T prNew,
+    IN P_LINK_T prLink
+    )
+{
+    __linkAdd(prNew, prLink->prPrev, (P_LINK_ENTRY_T)prLink);
+
+    return;
+} /* 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)
+*/
+/*----------------------------------------------------------------------------*/
+__KAL_INLINE__ VOID
+__linkDel (
+    IN P_LINK_ENTRY_T prPrev,
+    IN P_LINK_ENTRY_T prNext
+    )
+{
+    prNext->prPrev = prPrev;
+    prPrev->prNext = prNext;
+
+    return;
+} /* 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)
+*/
+/*----------------------------------------------------------------------------*/
+__KAL_INLINE__ VOID
+linkDel (
+    IN P_LINK_ENTRY_T prEntry
+    )
+{
+    __linkDel(prEntry->prPrev, prEntry->prNext);
+
+    LINK_ENTRY_INITIALIZE(prEntry);
+
+    return;
+} /* 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)
+*/
+/*----------------------------------------------------------------------------*/
+__KAL_INLINE__ VOID
+linkMove (
+    IN P_LINK_ENTRY_T prEntry,
+    IN P_LINK_T prLink
+    )
+{
+    __linkDel(prEntry->prPrev, prEntry->prNext);
+    linkAdd(prEntry, prLink);
+
+    return;
+} /* 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)
+*/
+/*----------------------------------------------------------------------------*/
+__KAL_INLINE__ VOID
+linkMoveTail (
+    IN P_LINK_ENTRY_T prEntry,
+    IN P_LINK_T prLink
+    )
+{
+    __linkDel(prEntry->prPrev, prEntry->prNext);
+    linkAddTail(prEntry, prLink);
+
+    return;
+} /* end of linkMoveTail() */
+
+#endif /* _LINK_H */
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/aa_fsm.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/aa_fsm.h
new file mode 100755 (executable)
index 0000000..1e7630c
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+** $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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/ais_fsm.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/ais_fsm.h
new file mode 100755 (executable)
index 0000000..b153256
--- /dev/null
@@ -0,0 +1,680 @@
+/*
+** $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 backgroud 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_DISCONNECT_SEC    10
+
+#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        2000
+
+/*******************************************************************************
+*                             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_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_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_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;
+
+    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;
+
+} 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
+    );
+
+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
+    );
+
+/*----------------------------------------------------------------------------*/
+/* 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,
+    UINT_32 u4Param
+    );
+
+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
+    );
+
+/*----------------------------------------------------------------------------*/
+/* Disconnection Handling                                                     */
+/*----------------------------------------------------------------------------*/
+VOID
+aisFsmDisconnect (
+    IN P_ADAPTER_T prAdapter,
+    IN BOOLEAN     fgDelayIndication
+    );
+
+
+/*----------------------------------------------------------------------------*/
+/* Event Handling                                                             */
+/*----------------------------------------------------------------------------*/
+VOID
+aisBssBeaconTimeout (
+    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,
+    UINT_32 u4Param
+    );
+
+VOID
+aisFsmRunEventIbssAloneTimeOut (
+    IN P_ADAPTER_T prAdapter,
+    UINT_32 u4Param
+    );
+
+VOID
+aisFsmRunEventJoinTimeout (
+    IN P_ADAPTER_T prAdapter,
+    UINT_32 u4Param
+    );
+
+/*----------------------------------------------------------------------------*/
+/* 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
+    );
+
+
+#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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/assoc.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/assoc.h
new file mode 100755 (executable)
index 0000000..1dbb06e
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+** $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                                                        */
+/*----------------------------------------------------------------------------*/
+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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/auth.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/auth.h
new file mode 100755 (executable)
index 0000000..6a8bf18
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+** $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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/bow_fsm.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/bow_fsm.h
new file mode 100755 (executable)
index 0000000..2e63f91
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+** $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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/bss.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/bss.h
new file mode 100755 (executable)
index 0000000..b7ff943
--- /dev/null
@@ -0,0 +1,353 @@
+/*
+** $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
+    );
+
+
+/*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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/cnm.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/cnm.h
new file mode 100755 (executable)
index 0000000..ec41a11
--- /dev/null
@@ -0,0 +1,323 @@
+/*
+** $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
+    );
+
+/*******************************************************************************
+*                              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.
+ */
+__KAL_INLINE__ VOID
+cnmMsgDataTypeCheck (
+    VOID
+    )
+{
+    DATA_STRUC_INSPECTING_ASSERT(
+        OFFSET_OF(MSG_CH_GRANT_T,rMsgHdr) == 0);
+
+    DATA_STRUC_INSPECTING_ASSERT(
+        OFFSET_OF(MSG_CH_GRANT_T,rMsgHdr) ==
+        OFFSET_OF(MSG_CH_RECOVER_T,rMsgHdr));
+
+    DATA_STRUC_INSPECTING_ASSERT(
+        OFFSET_OF(MSG_CH_GRANT_T,ucNetTypeIndex) ==
+        OFFSET_OF(MSG_CH_RECOVER_T,ucNetTypeIndex));
+
+    DATA_STRUC_INSPECTING_ASSERT(
+        OFFSET_OF(MSG_CH_GRANT_T,ucTokenID) ==
+        OFFSET_OF(MSG_CH_RECOVER_T,ucTokenID));
+
+    DATA_STRUC_INSPECTING_ASSERT(
+        OFFSET_OF(MSG_CH_GRANT_T,ucPrimaryChannel) ==
+        OFFSET_OF(MSG_CH_RECOVER_T,ucPrimaryChannel));
+
+    DATA_STRUC_INSPECTING_ASSERT(
+        OFFSET_OF(MSG_CH_GRANT_T,eRfSco) ==
+        OFFSET_OF(MSG_CH_RECOVER_T,eRfSco));
+
+    DATA_STRUC_INSPECTING_ASSERT(
+        OFFSET_OF(MSG_CH_GRANT_T,eRfBand) ==
+        OFFSET_OF(MSG_CH_RECOVER_T,eRfBand));
+
+    DATA_STRUC_INSPECTING_ASSERT(
+        OFFSET_OF(MSG_CH_GRANT_T,eReqType) ==
+        OFFSET_OF(MSG_CH_RECOVER_T,eReqType));
+
+    return;
+}
+#endif /* _lint */
+
+#endif /* _CNM_H */
+
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/cnm_mem.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/cnm_mem.h
new file mode 100755 (executable)
index 0000000..ae08428
--- /dev/null
@@ -0,0 +1,1159 @@
+/*
+** $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;
+
+    BOOL                    fg2nd1xSend;
+    BOOL                    fgKeyStored;
+
+    UINT_8                  aucStoredKey[64];
+
+    BOOL                    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;
+
+
+/* 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 choosen 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 Alogrithm 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. Chnage 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 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 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 requred 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
+    );
+
+/*******************************************************************************
+*                              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.
+ */
+__KAL_INLINE__ VOID
+cnmMemDataTypeCheck (
+    VOID
+    )
+{
+#if 0
+    DATA_STRUC_INSPECTING_ASSERT(
+        OFFSET_OF(MSDU_INFO_T,rLinkEntry) == 0);
+
+    DATA_STRUC_INSPECTING_ASSERT(
+        OFFSET_OF(MSDU_INFO_T,rLinkEntry) == OFFSET_OF(SW_RFB_T,rLinkEntry));
+
+    DATA_STRUC_INSPECTING_ASSERT(
+        OFFSET_OF(MSDU_INFO_T,pucBuffer) == OFFSET_OF(SW_RFB_T,pucBuffer));
+
+    DATA_STRUC_INSPECTING_ASSERT(
+        OFFSET_OF(MSDU_INFO_T,ucBufferSource) ==
+        OFFSET_OF(SW_RFB_T,ucBufferSource));
+
+    DATA_STRUC_INSPECTING_ASSERT(
+        OFFSET_OF(MSDU_INFO_T,pucMacHeader) ==
+        OFFSET_OF(SW_RFB_T,pucMacHeader));
+
+    DATA_STRUC_INSPECTING_ASSERT(
+        OFFSET_OF(MSDU_INFO_T,ucMacHeaderLength) ==
+        OFFSET_OF(SW_RFB_T,ucMacHeaderLength));
+
+    DATA_STRUC_INSPECTING_ASSERT(
+        OFFSET_OF(MSDU_INFO_T,pucPayload) ==
+        OFFSET_OF(SW_RFB_T,pucPayload));
+
+    DATA_STRUC_INSPECTING_ASSERT(
+        OFFSET_OF(MSDU_INFO_T,u2PayloadLength) ==
+        OFFSET_OF(SW_RFB_T,u2PayloadLength));
+
+    DATA_STRUC_INSPECTING_ASSERT(
+        OFFSET_OF(MSDU_INFO_T,prStaRec) ==
+        OFFSET_OF(SW_RFB_T,prStaRec));
+
+    DATA_STRUC_INSPECTING_ASSERT(
+        OFFSET_OF(MSDU_INFO_T,ucNetworkTypeIndex) ==
+        OFFSET_OF(SW_RFB_T,ucNetworkTypeIndex));
+
+    DATA_STRUC_INSPECTING_ASSERT(
+        OFFSET_OF(MSDU_INFO_T,ucTID) ==
+        OFFSET_OF(SW_RFB_T,ucTID));
+
+    DATA_STRUC_INSPECTING_ASSERT(
+        OFFSET_OF(MSDU_INFO_T,fgIs802_11Frame) ==
+        OFFSET_OF(SW_RFB_T,fgIs802_11Frame));
+
+    DATA_STRUC_INSPECTING_ASSERT(
+        OFFSET_OF(MSDU_INFO_T,ucControlFlag) ==
+        OFFSET_OF(SW_RFB_T,ucControlFlag));
+
+    DATA_STRUC_INSPECTING_ASSERT(
+        OFFSET_OF(MSDU_INFO_T,rArrivalTime) ==
+        OFFSET_OF(SW_RFB_T,rArrivalTime));
+
+    DATA_STRUC_INSPECTING_ASSERT(
+        OFFSET_OF(MSDU_INFO_T,ucTC) ==
+        OFFSET_OF(SW_RFB_T,ucTC));
+
+#if CFG_PROFILE_BUFFER_TRACING
+    DATA_STRUC_INSPECTING_ASSERT(
+        OFFSET_OF(MSDU_INFO_T,eActivity[0]) ==
+        OFFSET_OF(SW_RFB_T,eActivity[0]));
+
+    DATA_STRUC_INSPECTING_ASSERT(
+        OFFSET_OF(MSDU_INFO_T,rActivityTime[0]) ==
+        OFFSET_OF(SW_RFB_T,rActivityTime[0]));
+#endif
+
+#if DBG && CFG_BUFFER_FREE_CHK
+    DATA_STRUC_INSPECTING_ASSERT(
+        OFFSET_OF(MSDU_INFO_T,fgBufferInSource) ==
+        OFFSET_OF(SW_RFB_T,fgBufferInSource));
+#endif
+
+
+    DATA_STRUC_INSPECTING_ASSERT(
+        OFFSET_OF(STA_RECORD_T,rLinkEntry) == 0);
+
+    return;
+#endif
+}
+#endif /* _lint */
+
+#endif /* _CNM_MEM_H */
+
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/cnm_scan.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/cnm_scan.h
new file mode 100755 (executable)
index 0000000..b3d2993
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+** $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          32
+
+/*******************************************************************************
+*                             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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/cnm_timer.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/cnm_timer.h
new file mode 100755 (executable)
index 0000000..b1ed2c6
--- /dev/null
@@ -0,0 +1,274 @@
+/*
+** $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, UINT_32);
+
+typedef struct _TIMER_T {
+    LINK_ENTRY_T            rLinkEntry;
+    OS_SYSTIME              rExpiredSysTime;
+    UINT_16                 u2Minutes;
+    UINT_16                 u2Reserved;
+    UINT_32                 u4Data;
+    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), (UINT_32)(_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 UINT_32                  u4Data
+    );
+
+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
+********************************************************************************
+*/
+__KAL_INLINE__
+INT_32
+timerPendingTimer (
+    IN P_TIMER_T prTimer
+    )
+{
+    ASSERT(prTimer);
+
+    return prTimer->rLinkEntry.prNext != NULL;
+}
+
+#endif /* _CNM_TIMER_H */
+
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/hem_mbox.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/hem_mbox.h
new file mode 100755 (executable)
index 0000000..c86099c
--- /dev/null
@@ -0,0 +1,444 @@
+/*
+** $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.[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,
+#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 */
+
+    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;
+
+
+
+/* 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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/mib.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/mib.h
new file mode 100755 (executable)
index 0000000..febcfb5
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+** $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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_assoc.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_assoc.h
new file mode 100755 (executable)
index 0000000..270d1d6
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+** $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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_bss.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_bss.h
new file mode 100755 (executable)
index 0000000..a609476
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+** $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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_fsm.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_fsm.h
new file mode 100755 (executable)
index 0000000..9cd9b36
--- /dev/null
@@ -0,0 +1,2778 @@
+/*
+** $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 Channle 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;
+
+
+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;
+} 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
+}
+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;
+
+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 aucWfdVideolp[4];
+    UINT_8 aucWfdAudiolp[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_8   aucReverved2[56];
+    /* Group 2 64 bytes */
+    UINT_8   aucReverved3[64];
+    /* Group 3 64 bytes */
+    UINT_8   aucReverved4[64];
+
+};
+
+#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;
+#endif
+
+};
+
+
+/*---------------- 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
+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//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) */
+
+/* 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;              /* Prefered 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;
+
+    /* Extened 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_STRUC_T rNoaParam;
+    PARAM_CUSTOM_OPPPS_PARAM_STRUC_T rOppPsParam;
+
+};
+
+
+
+
+
+
+
+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) \
+            (_prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX].eConnectionState = (_eNewMediaState));
+
+#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 UINT_32 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.
+ */
+__KAL_INLINE__ VOID
+p2pDataTypeCheck (
+    VOID
+    )
+{
+    DATA_STRUC_INSPECTING_ASSERT(sizeof(IE_P2P_T) == (2+4+1)); // all UINT_8
+    DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRIBUTE_T) == (3+1));
+    DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_STATUS_T) == (3+1));
+    DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_REASON_T) == (3+1));
+    DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_CAPABILITY_T) == (3+2));
+    DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_DEV_ID_T) == (3+6));
+    DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_GO_INTENT_T) == (3+1));
+    DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_CFG_TIMEOUT_T) == (3+2));
+#if CID52_53_54
+    DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_LISTEN_CHANNEL_T) == (3+5));
+#else
+    DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_LISTEN_CHANNEL_T) == (3+5));
+#endif
+    DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_GROUP_BSSID_T) == (3+6));
+    DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_EXT_LISTEN_TIMING_T) == (3+4));
+    DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_INTENDED_IF_ADDR_T) == (3+6));
+    DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_MANAGEABILITY_T) == (3+1));
+
+    DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_CHANNEL_T) == (3+4));
+    DATA_STRUC_INSPECTING_ASSERT(sizeof(CHANNEL_ENTRY_FIELD_T) == 3);
+    DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_NOA_T) == (3+3));
+    DATA_STRUC_INSPECTING_ASSERT(sizeof(NOA_DESCRIPTOR_T) == 13);
+    DATA_STRUC_INSPECTING_ASSERT(sizeof(DEVICE_TYPE_T) == 8);
+    DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_DEV_INFO_T) == (3+6+2+8+1+8));
+    DATA_STRUC_INSPECTING_ASSERT(sizeof(DEVICE_NAME_TLV_T) == (4+32));
+    DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_CLIENT_INFO_DESC_T) == (1+6+6+1+2+8+1+8));
+    DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_GROUP_INFO_T) == (3+(1+6+6+1+2+8+1+8)));
+    DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_GROUP_ID_T) == (3+38));
+    DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_INTERFACE_T) == (3+13));
+#if CID52_53_54
+    DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_OPERATING_CHANNEL_T) == (3+5));
+#else
+    DATA_STRUC_INSPECTING_ASSERT(sizeof(P2P_ATTRI_OPERATING_CHANNEL_T) == (3+5));
+#endif
+
+
+    return;
+}
+#endif /* _lint */
+
+#endif /* _P2P_FSM_H */
+
+
+
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_func.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_func.h
new file mode 100755 (executable)
index 0000000..d767605
--- /dev/null
@@ -0,0 +1,350 @@
+#ifndef _P2P_FUNC_H
+#define _P2P_FUNC_H
+
+
+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
+    );
+
+#endif
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_ie.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_ie.h
new file mode 100755 (executable)
index 0000000..e632054
--- /dev/null
@@ -0,0 +1,232 @@
+#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
+
+
+
+#endif
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_rlm.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_rlm.h
new file mode 100755 (executable)
index 0000000..fe20ac3
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+** $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
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                              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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_rlm_obss.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_rlm_obss.h
new file mode 100755 (executable)
index 0000000..fa93d94
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+** $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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_scan.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_scan.h
new file mode 100755 (executable)
index 0000000..8ba3199
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+** $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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_state.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/p2p_state.h
new file mode 100755 (executable)
index 0000000..22bcf17
--- /dev/null
@@ -0,0 +1,89 @@
+#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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/privacy.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/privacy.h
new file mode 100755 (executable)
index 0000000..8f6ffd1
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+** $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
+   );
+
+BOOL
+secCheckClassError(
+    IN P_ADAPTER_T          prAdapter,
+    IN P_SW_RFB_T           prSwRfb,
+    IN P_STA_RECORD_T       prStaRec
+    );
+
+BOOL
+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
+    );
+
+BOOL
+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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/rate.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/rate.h
new file mode 100755 (executable)
index 0000000..74c4bb0
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+** $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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/rlm.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/rlm.h
new file mode 100755 (executable)
index 0000000..197202f
--- /dev/null
@@ -0,0 +1,451 @@
+/*
+** $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
+    );
+
+
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+
+#ifndef _lint
+__KAL_INLINE__ VOID
+rlmDataTypeCheck (
+    VOID
+    )
+{
+#if CFG_ENABLE_BT_OVER_WIFI
+    DATA_STRUC_INSPECTING_ASSERT(
+        NETWORK_TYPE_AIS_INDEX < NETWORK_TYPE_BOW_INDEX);
+
+    #if CFG_ENABLE_WIFI_DIRECT
+        DATA_STRUC_INSPECTING_ASSERT(
+            NETWORK_TYPE_P2P_INDEX < NETWORK_TYPE_BOW_INDEX);
+    #endif
+#endif
+
+    return;
+}
+#endif /* _lint */
+
+#endif /* _RLM_H */
+
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/rlm_domain.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/rlm_domain.h
new file mode 100755 (executable)
index 0000000..fda0137
--- /dev/null
@@ -0,0 +1,358 @@
+/*
+** $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 channle 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 COUNTRY_CODE_NULL               ((UINT_16)0x0)
+
+/* ISO/IEC 3166-1 two-character country codes */
+#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_AR (((UINT_16) 'A' << 8) | (UINT_16) 'T') /* Argentina     */
+#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_BB (((UINT_16) 'B' << 8) | (UINT_16) 'B') /* Barbados      */
+#define COUNTRY_CODE_BE (((UINT_16) 'B' << 8) | (UINT_16) 'E') /* Belgium       */
+#define COUNTRY_CODE_BM (((UINT_16) 'B' << 8) | (UINT_16) 'M') /* Bermuda       */
+#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_BY (((UINT_16) 'B' << 8) | (UINT_16) 'Y') /* Belarus       */
+#define COUNTRY_CODE_CA (((UINT_16) 'C' << 8) | (UINT_16) 'A') /* Canada        */
+#define COUNTRY_CODE_CH (((UINT_16) 'C' << 8) | (UINT_16) 'H') /* Switzerland   */
+#define COUNTRY_CODE_CL (((UINT_16) 'C' << 8) | (UINT_16) 'L') /* Chile         */
+#define COUNTRY_CODE_CN (((UINT_16) 'C' << 8) | (UINT_16) 'N') /* China         */
+#define COUNTRY_CODE_CO (((UINT_16) 'C' << 8) | (UINT_16) 'O') /* Colombia      */
+#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_DE (((UINT_16) 'D' << 8) | (UINT_16) 'E') /* Germany       */
+#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_EC (((UINT_16) 'E' << 8) | (UINT_16) 'C') /* Ecuador       */
+#define COUNTRY_CODE_EG (((UINT_16) 'E' << 8) | (UINT_16) 'G') /* Egypt         */
+#define COUNTRY_CODE_ES (((UINT_16) 'E' << 8) | (UINT_16) 'S') /* Spain         */
+#define COUNTRY_CODE_EU (((UINT_16) 'E' << 8) | (UINT_16) 'U') /* ETSI (Europe) */
+#define COUNTRY_CODE_FI (((UINT_16) 'F' << 8) | (UINT_16) 'I') /* Finland       */
+#define COUNTRY_CODE_FR (((UINT_16) 'F' << 8) | (UINT_16) 'R') /* France        */
+#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_GR (((UINT_16) 'G' << 8) | (UINT_16) 'R') /* Greece        */
+#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_HT (((UINT_16) 'H' << 8) | (UINT_16) 'T') /* Haiti         */
+#define COUNTRY_CODE_HN (((UINT_16) 'H' << 8) | (UINT_16) 'N') /* Honduras      */
+#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_IN (((UINT_16) 'I' << 8) | (UINT_16) 'N') /* India         */
+#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_JM (((UINT_16) 'J' << 8) | (UINT_16) 'M') /* Jamaica       */
+#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_KN (((UINT_16) 'K' << 8) | (UINT_16) 'N') /* Saint Kitts and Nevis */
+#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_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_LU (((UINT_16) 'L' << 8) | (UINT_16) 'U') /* Luxembourg    */
+#define COUNTRY_CODE_MA (((UINT_16) 'M' << 8) | (UINT_16) 'A') /* Morocco       */
+#define COUNTRY_CODE_MD (((UINT_16) 'M' << 8) | (UINT_16) 'D') /* Moldova       */
+#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_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_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_PE (((UINT_16) 'P' << 8) | (UINT_16) 'E') /* Peru          */
+#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_PR (((UINT_16) 'P' << 8) | (UINT_16) 'R') /* Puerto Rico   */
+#define COUNTRY_CODE_PT (((UINT_16) 'P' << 8) | (UINT_16) 'T') /* Portugal      */
+#define COUNTRY_CODE_PY (((UINT_16) 'P' << 8) | (UINT_16) 'Y') /* Paraguay      */
+#define COUNTRY_CODE_PZ (((UINT_16) 'P' << 8) | (UINT_16) 'Z') /* Panama        */
+#define COUNTRY_CODE_RU (((UINT_16) 'R' << 8) | (UINT_16) 'U') /* Russian       */
+#define COUNTRY_CODE_SA (((UINT_16) 'S' << 8) | (UINT_16) 'A') /* Saudi Arabia  */
+#define COUNTRY_CODE_SE (((UINT_16) 'S' << 8) | (UINT_16) 'E') /* Sweden        */
+#define COUNTRY_CODE_SG (((UINT_16) 'S' << 8) | (UINT_16) 'G') /* Singapore     */
+#define COUNTRY_CODE_SR (((UINT_16) 'S' << 8) | (UINT_16) 'R') /* Suriname      */
+#define COUNTRY_CODE_TW (((UINT_16) 'T' << 8) | (UINT_16) 'W') /* Taiwan        */
+#define COUNTRY_CODE_TH (((UINT_16) 'T' << 8) | (UINT_16) 'H') /* Thailand      */
+#define COUNTRY_CODE_TR (((UINT_16) 'T' << 8) | (UINT_16) 'R') /* Turkey        */
+#define COUNTRY_CODE_TT (((UINT_16) 'T' << 8) | (UINT_16) 'T') /* Trinidad      */
+#define COUNTRY_CODE_UA (((UINT_16) 'U' << 8) | (UINT_16) 'A') /* Ukraine       */
+#define COUNTRY_CODE_US (((UINT_16) 'U' << 8) | (UINT_16) 'S') /* United States */
+#define COUNTRY_CODE_UY (((UINT_16) 'U' << 8) | (UINT_16) 'Y') /* Uruguay       */
+#define COUNTRY_CODE_VC (((UINT_16) 'V' << 8) | (UINT_16) 'C') /* Saint Vincent */
+#define COUNTRY_CODE_VE (((UINT_16) 'V' << 8) | (UINT_16) 'E') /* Venezuela     */
+#define COUNTRY_CODE_VN (((UINT_16) 'V' << 8) | (UINT_16) 'N') /* Vietnam       */
+
+/* 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 */
+
+
+/*******************************************************************************
+*                             D A T A   T Y P E S
+********************************************************************************
+*/
+
+/* 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;
+
+#if 0
+/* If channel width is CHNL_BW_20_40, 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 {
+    UINT_8              ucRegClass;
+    ENUM_BAND_T         eBand;
+    ENUM_CHNL_SPAN_T    eChannelSpan;
+    UINT_8              ucFirstChannelNum;
+    UINT_8              ucNumChannels;
+    ENUM_CHNL_BW_T      eChannelBw;
+    BOOLEAN             fgDfsNeeded;
+    BOOLEAN             fgIbssProhibited;
+} DOMAIN_SUBBAND_INFO, *P_DOMAIN_SUBBAND_INFO;
+
+/* Use it as all available channel list for STA */
+typedef struct _DOMAIN_INFO_ENTRY {
+    UINT_16             u2CountryCode;
+    UINT_16             u2MibRegDomainValue;
+
+    /* 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;
+
+#else /* New definition 20110830 */
+
+/* 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              ucReserved;         /* Type: BOOLEAN (fgDfsNeeded) */
+} 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;
+#endif
+
+/* The following definitions are not used yet */
+typedef enum _ENUM_CH_SET_2G4_T {
+    CH_SET_2G4_NA,
+    CH_SET_2G4_1_11,
+    CH_SET_2G4_1_13,
+    CH_SET_2G4_1_14,
+    CH_SET_2G4_NUM
+} ENUM_CH_SET_2G4_T, *P_ENUM_CH_SET_2G4_T;
+
+typedef enum _ENUM_CH_SET_UNII_LOW_T {
+    CH_SET_UNII_LOW_NA,
+    CH_SET_UNII_LOW_36_48,
+    CH_SET_UNII_LOW_NUM
+} ENUM_CH_SET_UNII_LOW_T, *P_ENUM_CH_SET_UNII_LOW_T;
+
+typedef enum _ENUM_CH_SET_UNII_MID_T {
+    CH_SET_UNII_MID_NA,
+    CH_SET_UNII_MID_52_64,
+    CH_SET_UNII_MID_NUM
+} ENUM_CH_SET_UNII_MID_T, *P_ENUM_CH_SET_UNII_MID_T;
+
+typedef enum _ENUM_CH_SET_UNII_WW_T {
+    CH_SET_UNII_WW_NA,
+    CH_SET_UNII_WW_100_128,
+    CH_SET_UNII_WW_100_140,
+    CH_SET_UNII_WW_100_116_132_140,
+    CH_SET_UNII_WW_NUM
+} ENUM_CH_SET_UNII_WW_T, *P_ENUM_CH_SET_UNII_WW_T;
+
+typedef enum _ENUM_CH_SET_UNII_UPPER_T {
+    CH_SET_UNII_UPPER_NA,
+    CH_SET_UNII_UPPER_149_161,
+    CH_SET_UNII_UPPER_149_165,
+    CH_SET_UNII_UPPER_149_173,
+    CH_SET_UNII_UPPER_NUM
+} ENUM_CH_SET_UNII_UPPER_T, *P_ENUM_CH_SET_UNII_UPPER_T;
+
+typedef struct _COUNTRY_CH_SET_T {
+    ENUM_CH_SET_2G4_T           e2G4;
+    ENUM_CH_SET_UNII_LOW_T      eUniiLow;
+    ENUM_CH_SET_UNII_MID_T      eUniiMid;
+    ENUM_CH_SET_UNII_WW_T       eUniiWw;
+    ENUM_CH_SET_UNII_UPPER_T    eUniiUpper;
+} COUNTRY_CH_SET_T, *P_COUNTRY_CH_SET_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
+********************************************************************************
+*/
+P_DOMAIN_INFO_ENTRY
+rlmDomainGetDomainInfo (
+    P_ADAPTER_T     prAdapter
+    );
+
+VOID
+rlmDomainGetChnlList (
+    P_ADAPTER_T             prAdapter,
+    ENUM_BAND_T             eSpecificBand,
+    UINT_8                  ucMaxChannelNum,
+    PUINT_8                 pucNumOfChannel,
+    P_RF_CHANNEL_INFO_T     paucChannelList
+    );
+
+VOID
+rlmDomainSendCmd (
+    P_ADAPTER_T     prAdapter,
+    BOOLEAN         fgIsOid
+    );
+
+BOOLEAN
+rlmDomainIsLegalChannel (
+    P_ADAPTER_T     prAdapter,
+    ENUM_BAND_T     eBand,
+    UINT_8          ucChannel
+    );
+
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+
+#endif /* _RLM_DOMAIN_H */
+
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/rlm_obss.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/rlm_obss.h
new file mode 100755 (executable)
index 0000000..20533c9
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+** $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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/rlm_protection.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/rlm_protection.h
new file mode 100755 (executable)
index 0000000..6025b90
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+** $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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/roaming_fsm.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/roaming_fsm.h
new file mode 100755 (executable)
index 0000000..2a744f7
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+** $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;
+
+typedef struct _ROAMING_PARAM_T {
+    UINT_16     u2Event;
+    UINT_16     u2Data;
+} 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;
+
+} 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 UINT_32 u4Param
+    );    
+
+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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/rsn.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/rsn.h
new file mode 100755 (executable)
index 0000000..e18b201
--- /dev/null
@@ -0,0 +1,386 @@
+/*
+** $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  UINT_32           u4Parm
+    );
+#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
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+
+#endif /* _RSN_H */
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/scan.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/scan.h
new file mode 100755 (executable)
index 0000000..85ab712
--- /dev/null
@@ -0,0 +1,847 @@
+/*
+** $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 extention 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
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                              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.
+                                               */
+
+#define SCN_BSS_DESC_REMOVE_TIMEOUT_SEC     5 // 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.
+
+/*----------------------------------------------------------------------------*/
+/* 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                        4
+
+
+/*******************************************************************************
+*                             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;
+
+
+
+/*----------------------------------------------------------------------------*/
+/* 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;
+    BOOL                    fgIEWAPI;
+#endif
+    BOOL                    fgIERSN;
+    BOOL                    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;
+    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                 u2IELength; /* The byte count of aucIEBuf[] */
+
+    ULARGE_INTEGER          u8TimeStamp; /* Place u8TimeStamp before aucIEBuf[1] to force DW align */
+
+    UINT_8                  aucIEBuf[CFG_IE_BUFFER_SIZE];
+};
+
+
+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 _SCAN_INFO_T {
+    ENUM_SCAN_STATE_T       eCurrentState;  /* Store the STATE variable of SCAN FSM */
+
+    OS_SYSTIME              rLastScanCompletedTime;
+
+    SCAN_PARAM_T            rScanParam;
+
+    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;
+
+} 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;
+
+/*******************************************************************************
+*                            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
+    );
+
+
+/* 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
+    );
+
+/*----------------------------------------------------------------------------*/
+/* Routines in scan_fsm.c                                                     */
+/*----------------------------------------------------------------------------*/
+VOID
+scnFsmSteps (
+    IN P_ADAPTER_T prAdapter,
+    IN ENUM_SCAN_STATE_T eNextState
+    );
+
+/*----------------------------------------------------------------------------*/
+/* Command Routines                                                           */
+/*----------------------------------------------------------------------------*/
+VOID
+scnSendScanReq (
+    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
+    );
+
+/*----------------------------------------------------------------------------*/
+/* 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
+    );
+
+
+#endif /* _SCAN_H */
+
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/sec_fsm.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/sec_fsm.h
new file mode 100755 (executable)
index 0000000..17c6519
--- /dev/null
@@ -0,0 +1,284 @@
+/*
+** $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 UINT_32                u4Parm
+    );
+
+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 UINT_32              u4Parm
+    );
+
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+#endif /* _SEC_FSM_H */
+
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/swcr.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/swcr.h
new file mode 100755 (executable)
index 0000000..4ea322d
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+** $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
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                              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) \
+    index = action & 0x7F; \
+    rw = action >> 7; 
+
+
+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
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+*                              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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/wapi.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/wapi.h
new file mode 100755 (executable)
index 0000000..a47acae
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+** $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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/wlan_typedef.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/wlan_typedef.h
new file mode 100755 (executable)
index 0000000..2680a88
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+** $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;
+
+
+/* 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;
+
+/*******************************************************************************
+*                            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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/wnm.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/mgmt/wnm.h
new file mode 100755 (executable)
index 0000000..ac54cbc
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+** $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
+********************************************************************************
+*/
+
+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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/adapter.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/adapter.h
new file mode 100755 (executable)
index 0000000..098c30a
--- /dev/null
@@ -0,0 +1,1413 @@
+/*
+** $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 $
+**
+** 11 15 2012 cp.wu
+** [ALPS00382763] N820_JB:[WIFI]N820JB WLAN ±K???,«ÝÉó?¬y¥\¯Ó¤j
+** do not try reconnecting when being disconnected by the peer
+** 
+** 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) Chnage 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
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                              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_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
+    BOOL                            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  */
+};
+
+
+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;
+
+#if CFG_SLT_SUPPORT
+    SLT_INFO_T      rSltInfo;
+#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
+
+/*
+ * 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 */
+    /* <Todo> 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
+#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;
+
+    /* 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;
+
+    /* Packet Forwarding Tracking */
+    INT_32  i4PendingFwdFrameCount;
+
+#if CFG_SUPPORT_RDD_TEST_MODE
+    UINT_8  ucRddStatus;
+#endif
+
+    BOOL fgDisStaAgingTimeoutDetection;
+
+};/* 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
+********************************************************************************
+*/
+/*----------------------------------------------------------------------------*/
+/* 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
+
+/*----------------------------------------------------------------------------*/
+/* 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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/bow.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/bow.h
new file mode 100755 (executable)
index 0000000..d0be930
--- /dev/null
@@ -0,0 +1,323 @@
+/*
+** $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
+#define MAX_BOW_NUMBER_OF_CHANNEL                    18 //(MAX_BOW_NUMBER_OF_CHANNEL_2G4 + MAX_BOW_NUMBER_OF_CHANNEL_5G)
+
+#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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/cmd_buf.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/cmd_buf.h
new file mode 100755 (executable)
index 0000000..2bb10b9
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+** $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
+    );
+
+
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+#endif /* _CMD_BUF_H */
+
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/hal.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/hal.h
new file mode 100755 (executable)
index 0000000..e67727d
--- /dev/null
@@ -0,0 +1,609 @@
+/*
+** $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) \
+    { \
+        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", _u4Offset, *_pu4Value)); \
+            } \
+        } else { \
+            DBGLOG(HAL, WARN, ("ignore HAL_MCR_RD access! 0x%x\n", _u4Offset)); \
+        } \
+    }
+
+#define HAL_MCR_WR(_prAdapter, _u4Offset, _u4Value) \
+    { \
+        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", _u4Offset, _u4Value)); \
+            } \
+        } else { \
+            DBGLOG(HAL, WARN, ("ignore HAL_MCR_WR access! 0x%x: 0x%x \n", _u4Offset, _u4Value)); \
+        } \
+     }
+
+#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)); \
+        } \
+    }
+
+#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 { \
+            } \
+        } \
+        else { \
+            DBGLOG(HAL, WARN, ("ignore HAL_BYTE_WR access! 0x%x\n", _u4Port)); \
+        } \
+    }
+
+
+#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); \
+        } \
+        kalDevRegRead(_prAdapter->prGlueInfo, _u4Offset, _pu4Value); \
+    }
+
+#define HAL_MCR_WR(_prAdapter, _u4Offset, _u4Value) \
+    { \
+        if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \
+            ASSERT(0); \
+        } \
+        kalDevRegWrite(_prAdapter->prGlueInfo, _u4Offset, _u4Value); \
+    }
+
+#define HAL_PORT_RD(_prAdapter, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) \
+    { \
+        if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \
+            ASSERT(0); \
+        } \
+        kalDevPortRead(_prAdapter->prGlueInfo, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize); \
+    }
+
+#define HAL_PORT_WR(_prAdapter, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) \
+    { \
+        if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \
+            ASSERT(0); \
+        } \
+        kalDevPortWrite(_prAdapter->prGlueInfo, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize); \
+    }
+
+#define HAL_BYTE_WR(_prAdapter, _u4Port, _ucBuf) \
+    { \
+        if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \
+            ASSERT(0); \
+        } \
+        kalDevWriteWithSdioCmd52(_prAdapter->prGlueInfo, _u4Port, _ucBuf); \
+    }
+
+#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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/hif_rx.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/hif_rx.h
new file mode 100755 (executable)
index 0000000..3895a7c
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+** $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)
+
+// 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_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
+********************************************************************************
+*/
+__KAL_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.
+ */
+__KAL_INLINE__ VOID
+hifDataTypeCheck (
+    VOID
+    )
+{
+    DATA_STRUC_INSPECTING_ASSERT(sizeof(HIF_RX_HEADER_T) == 12);
+
+    return;
+}
+
+#endif
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/hif_tx.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/hif_tx.h
new file mode 100755 (executable)
index 0000000..3a04ce5
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+** $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)
+
+
+/*******************************************************************************
+*                         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.
+ */
+__KAL_INLINE__ VOID
+hif_txDataTypeCheck (
+    VOID
+    );
+
+__KAL_INLINE__ VOID
+hif_txDataTypeCheck (
+    VOID
+    )
+{
+    DATA_STRUC_INSPECTING_ASSERT(sizeof(HIF_TX_HEADER_T) == 16);
+
+    return;
+}
+
+#endif /*_HIF_TX_H */
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/mac.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/mac.h
new file mode 100755 (executable)
index 0000000..f22154b
--- /dev/null
@@ -0,0 +1,2185 @@
+/*
+** $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_PROTOCOL_OFFSET             9
+#define IPV4_HDR_IP_CSUM_OFFSET                 10
+
+#define IPV6_HDR_IP_PROTOCOL_OFFSET             6
+
+#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          32
+
+
+//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 */
+
+/* 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 becasue 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 */
+#if CFG_SUPPORT_802_11W
+#define ELEM_ID_TIMEOUT_INTERVAL                    56  /* 802.11w SA Timeout interval */
+#endif
+#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_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
+
+/* 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
+
+
+/* 7.3.2.25 RSN information element */
+#define ELEM_MAX_LEN_WPA                            24 /* 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_MAX_LEN_EXT_CAP                        (3 - ELEM_HDR_LEN)
+
+/* 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)   //WMM: Bit(7,8) = (1,0) = EDCA
+#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)
+
+
+//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_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
+
+
+//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;
+
+/* 7.3.2.20 Channel Switch Announcement element */
+typedef struct _IE_CHNL_SWITCH_T {
+    UINT_8      ucId;
+    UINT_8      ucLength;
+    UINT_8      ucSwitchMode;
+    UINT_8      ucNewChannel;
+    UINT_8      ucSwitchCount;
+} __KAL_ATTRIB_PACKED__ IE_CHNL_SWITCH_T, *P_IE_CHNL_SWITCH_T;
+
+/* 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[1];
+} __KAL_ATTRIB_PACKED__ IE_EXT_CAP_T, *P_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.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;
+
+
+//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.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;
+
+/* 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 QUIET_IE(fp)            ((P_IE_QUIET_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))
+
+/*******************************************************************************
+*                   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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/mt6620_reg.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/mt6620_reg.h
new file mode 100755 (executable)
index 0000000..3f2eacd
--- /dev/null
@@ -0,0 +1,286 @@
+/*
+** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/mt6620_reg.h#1 $
+*/
+
+/*! \file   "mt6620_reg.h"
+    \brief  The common register definition of mt6620
+
+    N/A
+*/
+
+
+
+/*
+** $Log: mt6620_reg.h $
+ *
+ * 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
+ *
+ * 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 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
+**  \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-12-10 16:44:18 GMT mtk02752
+**  remove 5921 definitions
+**  \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-11-09 22:56:32 GMT mtk01084
+**  modify HW register definitions
+**  \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-11-04 14:11:04 GMT mtk01084
+**  modify default IER bits
+**  \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-10-29 19:52:32 GMT mtk01084
+**  modify data struture
+**  \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-10-23 16:08:20 GMT mtk01084
+**  \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-10-13 21:58:53 GMT mtk01084
+**  update for new HW architecture design
+**  \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-09-09 17:26:11 GMT mtk01084
+**  add CFG_TEST_WITH_MT5921
+**  \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-05-18 20:59:57 GMT mtk01426
+**  Update WHIER_DEFAULT value
+**  \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-05-07 16:57:36 GMT mtk01426
+**  Update CHIP ID to 0x6620, and WHLPCR bit definition
+**  \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-04-28 10:34:57 GMT mtk01461
+**  Add read WTSR and fix RX STATUS is DW align for SDIO_STATUS_ENHANCE mode
+**  \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-03-24 09:46:52 GMT mtk01084
+**  fix LINT error
+**  \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-23 00:32:24 GMT mtk01461
+**  Define constants for TX PATH
+**  \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-18 20:54:10 GMT mtk01426
+**  Add WHCR_MAX_HIF_RX_AGG_LEN_OFFSET definition
+**  \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:16:29 GMT mtk01426
+**  Init for develop
+**
+*/
+
+#ifndef _MT6620_REG_H
+#define _MT6620_REG_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 MT6620 MCR Definition
+
+//2 Host Interface
+
+//4 CHIP ID Register
+#define MCR_WCIR                            0x0000
+
+//4 HIF Low Power Control  Register
+#define MCR_WHLPCR                          0x0004
+//#define MCR_WHLPCR_BYTE1                    0x0005
+
+
+//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 WLAN RX Packet Length Register
+#define MCR_WRPLR                           0x0048
+
+
+
+
+//temp //#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                     0x00006620
+#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_INT_INDICATOR          BIT(7)
+#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_INT_INDICATOR_EN       BIT(7)
+#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 WTSR0 0x0044
+#define WRPLR_RX1_PACKET_LENGTH         BITS(16,31)
+#define WRPLR_RX0_PACKET_LENGTH         BITS(0,15)
+
+#endif /* _MT6620_REG_H */
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/nic.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/nic.h
new file mode 100755 (executable)
index 0000000..6463138
--- /dev/null
@@ -0,0 +1,724 @@
+/*
+** $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 occured
+ *
+ * 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
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                            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
+    );
+
+BOOL
+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
+    );
+
+/*----------------------------------------------------------------------------*/
+/* 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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/nic_rx.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/nic_rx.h
new file mode 100755 (executable)
index 0000000..49ca299
--- /dev/null
@@ -0,0 +1,529 @@
+/*
+** $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
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                              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
+
+
+#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 */
+};
+
+/*! 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) \
+    ((BOOL)((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
+    );
+
+#if defined(MT5931)
+VOID
+nicRxPostInitialize (
+    IN P_ADAPTER_T prAdapter
+    );
+#endif
+
+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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/nic_tx.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/nic_tx.h
new file mode 100755 (executable)
index 0000000..4837da4
--- /dev/null
@@ -0,0 +1,646 @@
+/*
+** $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 availble 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(MT5931) 
+    #define NIC_TX_BUFF_COUNT_TC0       1   // First connection: 0
+    #define NIC_TX_BUFF_COUNT_TC1       14  // 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 defined(MT6628)
+    #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
+
+#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
+
+/*******************************************************************************
+*                             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;
+
+/* 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
+    );
+
+/* 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;
+};
+
+
+/*******************************************************************************
+*                            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));}
+
+
+
+/*******************************************************************************
+*                  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
+    );
+
+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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/p2p.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/p2p.h
new file mode 100755 (executable)
index 0000000..30bae79
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+** $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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/p2p_cmd_buf.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/p2p_cmd_buf.h
new file mode 100755 (executable)
index 0000000..c59c606
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+** $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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/p2p_mac.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/p2p_mac.h
new file mode 100755 (executable)
index 0000000..9c022b0
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+** $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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/p2p_nic.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/p2p_nic.h
new file mode 100755 (executable)
index 0000000..3f1363f
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+** $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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/p2p_nic_cmd_event.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/p2p_nic_cmd_event.h
new file mode 100755 (executable)
index 0000000..fb056ff
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+** $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
\ No newline at end of file
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/que_mgt.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/que_mgt.h
new file mode 100755 (executable)
index 0000000..fd31ecd
--- /dev/null
@@ -0,0 +1,1150 @@
+/*
+** $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) Chnage 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 */
+#define QM_BURST_END_INFO_ENABLED       1  /* 1: Indicate the last TX packet to the FW for each burst */
+#define QM_FORWARDING_FAIRNESS          1  /* 1: To fairly share TX resource among active STAs */
+#define QM_ADAPTIVE_TC_RESOURCE_CTRL    1  /* 1: To adaptively adjust resource for each TC */
+#define QM_PRINT_TC_RESOURCE_CTRL       0  /* 1: To print TC resource adjustment results */
+#define QM_RX_WIN_SSN_AUTO_ADVANCING    1  /* 1: If pkt with SSN is missing, auto advance the RX reordering window */
+#define QM_RX_INIT_FALL_BEHIND_PASS     1  /* 1: Indicate the packets falling behind to OS before the frame with SSN is received */
+/* Parameters */
+#define QM_INIT_TIME_TO_UPDATE_QUE_LEN  60  /* p: Update queue lengths when p TX packets are enqueued */
+#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(MT5931) 
+
+#define QM_GUARANTEED_TC0_RESOURCE      4
+#define QM_GUARANTEED_TC1_RESOURCE      4
+#define QM_GUARANTEED_TC2_RESOURCE      4 
+#define QM_GUARANTEED_TC3_RESOURCE      4
+#define QM_GUARANTEED_TC4_RESOURCE      2   /* Resource for TC4 is not adjustable */
+#define QM_GUARANTEED_TC5_RESOURCE      2
+
+#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 */
+#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;
+
+    /* 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
+
+
+
+
+} 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_TYEP_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
+    );
+
+VOID
+qmPopOutDueToFallWithin(
+    IN P_RX_BA_ENTRY_T prReorderQueParm,
+    OUT P_QUE_T prReturnedQue
+    );
+
+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
+    );
+
+BOOL
+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
+    );
+
+VOID
+mqmGenerateWmmInfoIE (
+    IN P_ADAPTER_T          prAdapter,
+    IN P_MSDU_INFO_T        prMsduInfo
+    );
+
+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
+    );
+
+VOID
+qmFreeAllByNetType(
+    IN P_ADAPTER_T prAdapter, 
+    IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx
+    );
+
+UINT_32
+qmGetRxReorderQueuedBufferCount(
+       IN P_ADAPTER_T  prAdapter
+       );
+   
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+
+#endif /* _QUE_MGT_H */
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/wlan_def.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic/wlan_def.h
new file mode 100755 (executable)
index 0000000..c9a7f18
--- /dev/null
@@ -0,0 +1,1012 @@
+/*
+** $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 $
+ *
+ * 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
+
+/* 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                  6
+#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_DLS_INDEX
+} 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_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 {
+    PHY_CONFIG_802_11ABG = 0,           /*!< Can associated with 802.11abg AP but without n capability, Scan dual band. */
+    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)
+
+/* 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)
+
+/* 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)
+} 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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic_cmd_event.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic_cmd_event.h
new file mode 100755 (executable)
index 0000000..17cb03d
--- /dev/null
@@ -0,0 +1,1892 @@
+/*
+** $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 extention 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 occured
+ *
+ * 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
+
+
+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,        /* 0x3A (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_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) */
+
+#if CFG_SUPPORT_RDD_TEST_MODE
+    CMD_ID_SET_RDD_CH = 0xE1,
+#endif
+
+    CMD_ID_SET_BWCS = 0xF1,
+#if CFG_SUPPORT_OSC_SETTING && defined(MT5931)
+    CMD_ID_SET_OSC = 0xf2,
+#endif
+
+} 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) */
+} 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
+/* 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_STRUC_T rRfATInfo;
+    } u;
+} CMD_TEST_CTRL_T, *P_CMD_TEST_CTRL_T;
+
+// EVENT_TEST_STATUS
+typedef struct _PARAM_CUSTOM_RFTEST_TX_STATUS_STRUC_T {
+    UINT_32             u4PktSentStatus;
+    UINT_32             u4PktSentCount;
+    UINT_16             u2AvgAlc;
+    UINT_8              ucCckGainControl;
+    UINT_8              ucOfdmGainControl;
+} PARAM_CUSTOM_RFTEST_TX_STATUS_STRUC_T, *P_PARAM_CUSTOM_RFTEST_TX_STATUS_STRUC_T;
+
+typedef struct  _PARAM_CUSTOM_RFTEST_RX_STATUS_STRUC_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_STRUC_T, *P_PARAM_CUSTOM_RFTEST_RX_STATUS_STRUC_T;
+
+typedef union _EVENT_TEST_STATUS {
+    PARAM_MTK_WIFI_TEST_STRUC_T             rATInfo;
+//    PARAM_CUSTOM_RFTEST_TX_STATUS_STRUC_T   rTxStatus;
+//    PARAM_CUSTOM_RFTEST_RX_STATUS_STRUC_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_STRUC_T {
+    UINT_32  u4NoaDurationMs;
+    UINT_32  u4NoaIntervalMs;
+    UINT_32  u4NoaCount;
+} CMD_CUSTOM_NOA_PARAM_STRUC_T, *P_CMD_CUSTOM_NOA_PARAM_STRUC_T;
+
+typedef struct _CMD_CUSTOM_OPPPS_PARAM_STRUC_T {
+    UINT_32  u4CTwindowMs;
+} CMD_CUSTOM_OPPPS_PARAM_STRUC_T, *P_CMD_CUSTOM_OPPPS_PARAM_STRUC_T;
+
+typedef struct _CMD_CUSTOM_UAPSD_PARAM_STRUC_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_STRUC_T, *P_CMD_CUSTOM_UAPSD_PARAM_STRUC_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
+    UINT_8      aucReserved[2];
+} 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;
+
+#if CFG_SUPPORT_OSC_SETTING && defined(MT5931)
+typedef struct _CMD_MCU_LP_PARAM_T {
+    UINT_16     u2OscStableTime;
+    UINT_8      ucReserved[6];
+} CMD_MCU_LP_PARAM_T, *P_CMD_MCU_LP_PARAM_T;
+#endif
+
+
+// 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_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             u2Reserved;
+    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;
+
+// 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  aucRsv[1];
+    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_STRUC_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_STRUC_T, *P_CMD_SET_WMM_PS_TEST_STRUC_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_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_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 extention. */
+    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;
+
+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(MT5931) || 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 paramters */
+    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 struct _EVENT_BSS_BEACON_TIMEOUT_T {
+    UINT_8  ucNetTypeIndex;
+    UINT_8  aucReserved[3];
+} 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_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 _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;
+
+/*******************************************************************************
+*                            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
+    );
+
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+
+#endif /* _NIC_CMD_EVENT_H */
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic_init_cmd_event.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/nic_init_cmd_event.h
new file mode 100755 (executable)
index 0000000..33886c9
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+** $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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/p2p_precomp.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/p2p_precomp.h
new file mode 100755 (executable)
index 0000000..892b5b7
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+** $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"
+#elif defined(MT5931)
+    #include "mt5931_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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/p2p_typedef.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/p2p_typedef.h
new file mode 100755 (executable)
index 0000000..c8aa47f
--- /dev/null
@@ -0,0 +1,278 @@
+/*
+** $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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/precomp.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/precomp.h
new file mode 100755 (executable)
index 0000000..0e5a8e3
--- /dev/null
@@ -0,0 +1,380 @@
+/*
+** $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(MT5931)
+    #include "mt5931_reg.h"
+#elif defined(MT6628)
+    #include "mt6628_reg.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"
+
+
+#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
+
+/*******************************************************************************
+*                              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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/pwr_mgt.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/pwr_mgt.h
new file mode 100755 (executable)
index 0000000..4819de0
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+** $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 adress & 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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/queue.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/queue.h
new file mode 100755 (executable)
index 0000000..a7773e9
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+** $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
+********************************************************************************
+*/
+#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) \
+        { \
+            ASSERT(prQueue); \
+            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) \
+        { \
+            ASSERT(prQueue); \
+            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) \
+        { \
+            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) \
+        { \
+            ASSERT(prDestQueue); \
+            ASSERT(prSrcQueue); \
+            *(P_QUE_T)prDestQueue = *(P_QUE_T)prSrcQueue; \
+            QUEUE_INITIALIZE(prSrcQueue); \
+        }
+
+#define QUEUE_CONCATENATE_QUEUES(prDestQueue, prSrcQueue) \
+        { \
+            ASSERT(prDestQueue); \
+            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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/rftest.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/rftest.h
new file mode 100755 (executable)
index 0000000..ae6541d
--- /dev/null
@@ -0,0 +1,317 @@
+/*
+** $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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/typedef.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/typedef.h
new file mode 100755 (executable)
index 0000000..5db05c0
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+** $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_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 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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/wlan_bow.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/wlan_bow.h
new file mode 100755 (executable)
index 0000000..a3c4d38
--- /dev/null
@@ -0,0 +1,547 @@
+/*
+** $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
+/*******************************************************************************
+*                              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,
+    UINT_32 u4Param
+    );
+
+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 UINT_32 u4Param
+    );
+
+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/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/wlan_lib.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/wlan_lib.h
new file mode 100755 (executable)
index 0000000..5141726
--- /dev/null
@@ -0,0 +1,1042 @@
+/*
+** $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"
+
+/*******************************************************************************
+*                              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)
+
+
+/*******************************************************************************
+*                             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;
+
+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;
+    // 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_STRUC_T {
+    UINT_32             u4McrOffset;
+    UINT_32             u4McrData;
+} PARAM_MCR_RW_STRUC_T, *P_PARAM_MCR_RW_STRUC_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 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
+    );
+
+BOOL
+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 UINT_32      u4Data
+    );
+
+VOID
+wlanReleasePendingCMDbyNetwork(
+    IN P_ADAPTER_T  prAdapter,
+    IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType
+    );
+
+VOID
+wlanReturnPacket (
+    IN P_ADAPTER_T prAdapter,
+    IN PVOID pvPacket
+    );
+
+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 Retreive by Polling                                                */
+/*----------------------------------------------------------------------------*/
+WLAN_STATUS
+wlanQueryPermanentAddress(
+    IN P_ADAPTER_T prAdapter
+    );
+
+
+/*----------------------------------------------------------------------------*/
+/* NIC Capability Retrieve by Polling                                         */
+/*----------------------------------------------------------------------------*/
+WLAN_STATUS
+wlanQueryNicCapability(
+    IN P_ADAPTER_T prAdapter
+    );
+
+
+/*----------------------------------------------------------------------------*/
+/* PD MCR Retrieve by Polling                                         */
+/*----------------------------------------------------------------------------*/
+WLAN_STATUS
+wlanQueryPdMcr(
+    IN P_ADAPTER_T prAdapter,
+    IN P_PARAM_MCR_RW_STRUC_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
+    );
+
+#if CFG_SUPPORT_OSC_SETTING && defined(MT5931)
+WLAN_STATUS
+wlanSetMcuOscStableTime (
+    IN P_ADAPTER_T      prAdapter,
+    IN UINT_16          u2OscStableTime
+    );
+#endif
+
+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
+    );
+
+
+#endif /* _WLAN_LIB_H */
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/wlan_oid.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/wlan_oid.h
new file mode 100755 (executable)
index 0000000..ea28d12
--- /dev/null
@@ -0,0 +1,2061 @@
+/*
+** $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
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                              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];
+} PARAM_SSID_T, *P_PARAM_SSID_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,
+    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_STRUC_T {
+    UINT_32             u4McrOffset;
+    UINT_32             u4McrData;
+} PARAM_CUSTOM_MCR_RW_STRUC_T, *P_PARAM_CUSTOM_MCR_RW_STRUC_T;
+
+typedef struct _PARAM_CUSTOM_MEM_DUMP_STRUC_T {
+    UINT_32     u4Address;
+    UINT_32     u4Length;
+    UINT_32     u4RemainLength;
+    UINT_8      ucFragNum;
+} PARAM_CUSTOM_MEM_DUMP_STRUC_T, *P_PARAM_CUSTOM_MEM_DUMP_STRUC_T;
+
+
+typedef struct _PARAM_CUSTOM_SW_CTRL_STRUC_T {
+    UINT_32             u4Id;
+    UINT_32             u4Data;
+} PARAM_CUSTOM_SW_CTRL_STRUC_T, *P_PARAM_CUSTOM_SW_CTRL_STRUC_T;
+
+
+typedef struct _PARAM_CUSTOM_EEPROM_RW_STRUC_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_STRUC_T, *P_PARAM_CUSTOM_EEPROM_RW_STRUC_T,
+    PARAM_CUSTOM_NVRAM_RW_STRUCT_T, *P_PARAM_CUSTOM_NVRAM_RW_STRUCT_T;
+
+typedef struct _PARAM_CUSTOM_WMM_PS_TEST_STRUC_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_STRUC_T, *P_PARAM_CUSTOM_WMM_PS_TEST_STRUC_T;
+
+typedef struct _PARAM_CUSTOM_NOA_PARAM_STRUC_T {
+    UINT_32  u4NoaDurationMs;
+    UINT_32  u4NoaIntervalMs;
+    UINT_32  u4NoaCount;
+} PARAM_CUSTOM_NOA_PARAM_STRUC_T, *P_PARAM_CUSTOM_NOA_PARAM_STRUC_T;
+
+typedef struct _PARAM_CUSTOM_OPPPS_PARAM_STRUC_T {
+    UINT_32  u4CTwindowMs;
+} PARAM_CUSTOM_OPPPS_PARAM_STRUC_T, *P_PARAM_CUSTOM_OPPPS_PARAM_STRUC_T;
+
+typedef struct _PARAM_CUSTOM_UAPSD_PARAM_STRUC_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_STRUC_T, *P_PARAM_CUSTOM_UAPSD_PARAM_STRUC_T;
+
+typedef struct _PARAM_CUSTOM_P2P_SET_STRUC_T {
+    UINT_32             u4Enable;
+    UINT_32             u4Mode;
+} PARAM_CUSTOM_P2P_SET_STRUC_T, *P_PARAM_CUSTOM_P2P_SET_STRUC_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_STRUC_T {
+    UINT_32                 u4FuncIndex;
+    UINT_32                 u4FuncData;
+} PARAM_MTK_WIFI_TEST_STRUC_T, *P_PARAM_MTK_WIFI_TEST_STRUC_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_STRUC_T {
+    ENUM_MTK_LP_TEST_MODE_T rLpTestMode;
+    UINT_32 u4BcnRcvNum;
+} PARAM_MTK_SLT_LP_TEST_STRUC_T, *P_PARAM_MTK_SLT_LP_TEST_STRUC_T;
+
+typedef struct _PARAM_MTK_SLT_TR_TEST_STRUC_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_STRUC_T, *P_PARAM_MTK_SLT_TR_TEST_STRUC_T;
+
+typedef struct _PARAM_MTK_SLT_INITIAL_STRUC_T {
+    UINT_8 aucTargetMacAddr[PARAM_MAC_ADDR_LEN];
+    UINT_16 u2SiteID;
+} PARAM_MTK_SLT_INITIAL_STRUC_T, *P_PARAM_MTK_SLT_INITIAL_STRUC_T;
+
+typedef struct _PARAM_MTK_SLT_TEST_STRUC_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_STRUC_T rMtkInitTest;
+        PARAM_MTK_SLT_LP_TEST_STRUC_T rMtkLpTest;
+        PARAM_MTK_SLT_TR_TEST_STRUC_T rMtkTRTest;
+    } unFuncInfoContent;
+
+} PARAM_MTK_SLT_TEST_STRUC_T, *P_PARAM_MTK_SLT_TEST_STRUC_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;
+
+
+/*******************************************************************************
+*                            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
+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,
+    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
+    );
+
+#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
+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
+    );
+
+/*
+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
+
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+
+#endif /* _WLAN_OID_H */
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/wlan_p2p.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/include/wlan_p2p.h
new file mode 100755 (executable)
index 0000000..c3c4509
--- /dev/null
@@ -0,0 +1,461 @@
+/*
+** $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 Channle 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;
+
+#if 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;
+    UINT_8   aucWfdLocalIp[4];
+    UINT_8      aucReserved2[64];
+    UINT_8      aucReserved3[64];
+    UINT_8      aucReserved4[64];
+}NL80211_DRIVER_WFD_PARAMS, *P_NL80211_DRIVER_WFD_PARAMS;
+#endif
+
+
+
+#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
+********************************************************************************
+*/
+
+/*--------------------------------------------------------------*/
+/* 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
+    );
+
+#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/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/aaa_fsm.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/aaa_fsm.c
new file mode 100755 (executable)
index 0000000..1d14793
--- /dev/null
@@ -0,0 +1,1490 @@
+/*
+** $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);
+
+    return;
+} /* 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);
+
+    }
+
+    return;
+} /* 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, WARN, ("Previous AuthAssocState (%d) != SEND_AUTH2.\n",
+                prStaRec->eAuthAssocState));
+            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 Assocation ID */
+
+                    /* If (Re)association fail, the peer can try Assocation 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 Assocation ID */
+
+                    /* If (Re)association fail, the peer can try Assocation 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 Assocation ID */
+
+            /* If (Re)association fail, the peer can try Assocation 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 = %ld\n", kalGetTimeTick()));
+
+    prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex);
+
+    if ((!prStaRec) || (!prStaRec->fgIsInUse)) {
+        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]);
+
+    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) {
+
+        /* Update Station Record - Class 1 Flag */
+        prStaRec->ucStaState = STA_STATE_1;
+    }
+#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);
+    }
+
+    return;
+} /* 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;
+
+    return;
+} /* 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);
+    return;
+} /* 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: ["MACSTR"]\n", MAC2STR(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 Infomation
+    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
+         * <AssocReq>     <AssocResp w/i ERP>     <BARKER(Long)>  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
+         * <AssocReq>     <AssocResp w/o ERP>     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);
+
+    return;
+} /* end of joinComplete() */
+#endif
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/ais_fsm.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/ais_fsm.c
new file mode 100755 (executable)
index 0000000..c13c860
--- /dev/null
@@ -0,0 +1,4641 @@
+/*
+** $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 $
+**
+** 11 15 2012 cp.wu
+** [ALPS00382763] N820_JB:[WIFI]N820JB WLAN ±K???,«ÝÉó?¬y¥\¯Ó¤j
+** do not try reconnecting when being disconnected by the peer
+ *
+ * 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 occured 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 occured
+ *
+ * 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 Microsoft 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 infomation 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 seperate 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
+
+/*******************************************************************************
+*                             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")
+};
+/*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);
+
+    prConnSettings->ucDelayTimeOfDisconnectEvent = AIS_DELAY_TIME_OF_DISCONNECT_SEC;
+
+    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;
+
+    return;
+} /* 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)
+*/
+/*----------------------------------------------------------------------------*/
+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, INFO, ("->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,
+            (UINT_32)NULL);
+
+    cnmTimerInitTimer(prAdapter,
+            &prAisFsmInfo->rIbssAloneTimer,
+            (PFN_MGMT_TIMEOUT_FUNC)aisFsmRunEventIbssAloneTimeOut,
+            (UINT_32)NULL);
+
+    cnmTimerInitTimer(prAdapter,
+            &prAisFsmInfo->rIndicationOfDisconnectTimer,
+            (PFN_MGMT_TIMEOUT_FUNC)aisPostponedEventOfDisconnTimeout,
+            (UINT_32)NULL);
+
+    cnmTimerInitTimer(prAdapter,
+            &prAisFsmInfo->rJoinTimeoutTimer,
+            (PFN_MGMT_TIMEOUT_FUNC)aisFsmRunEventJoinTimeout,
+            (UINT_32)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);
+
+    return;
+} /* 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);
+
+    //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
+
+    return;
+} /* 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);
+
+    prAisFsmInfo->prTargetStaRec = prStaRec;
+
+    //4 <2.1> sync. to firmware domain
+    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 (prConnSettings->eConnectionPolicy == CONNECT_BY_SSID_ANY) {
+
+        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);
+
+    return;
+} /* 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);
+
+    return;
+} /* 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);
+
+    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);
+
+    return;
+} /* 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;
+    }
+
+    kalIndicateStatusAndComplete(prAdapter->prGlueInfo,
+             WLAN_STATUS_CONNECT_INDICATION,
+             NULL,
+             0);
+
+    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;
+
+    return;
+} /* 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);
+
+    return;
+} /* 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);
+
+    /* 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;
+
+    return;
+} /* 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);
+
+    return;
+}
+#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;
+
+    BOOLEAN fgIsTransition = (BOOLEAN)FALSE;
+
+    DEBUGFUNC("aisFsmSteps()");
+
+    prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo);
+    prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]);
+    prConnSettings = &(prAdapter->rWifiVar.rConnSettings);
+
+    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);
+
+            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) {
+                        if(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);
+            }
+
+            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
+
+            // 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 <A> 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 <B> 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 <A> Try to SCAN
+                    if (prAisFsmInfo->fgTryScan) {
+                        eNextState = AIS_STATE_LOOKING_FOR;
+
+                        fgIsTransition = TRUE;
+                    }
+                    //4 <B> We've do SCAN already, now wait in some STATE.
+                    else {
+                        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 VI: Timestamp of the current AP might be reset
+                 */
+                if ((!prBssDesc) || /* CASE I */
+                    (prBssDesc->eBSSType != BSS_TYPE_INFRASTRUCTURE) || /* CASE II */
+                    (prBssDesc->fgIsConnected) || /* CASE III */
+                    (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prAisBssInfo->aucBSSID)) /* CASE VI */) {
+#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;
+                }
+                //4 <3.b> Try to roam out for JOIN this BSS_DESC_T.
+                else {
+#if DBG
+                    ASSERT(UNEQUAL_MAC_ADDR(prBssDesc->aucBSSID, prAisBssInfo->aucBSSID));
+#endif /* DBG */
+
+                    //4 <A> 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 = %ld\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(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(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);
+
+            prAisFsmInfo->fgTryScan = FALSE; /* Will enable background sleep for infrastructure */
+
+            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;
+            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;
+                }
+            }
+
+            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);
+            break;
+
+        default:
+            ASSERT(0); /* Make sure we have handle all STATEs */
+            break;
+
+        }
+    }
+    while (fgIsTransition);
+
+    return;
+
+} /* end of aisFsmSteps() */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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);
+
+    DBGLOG(AIS, LOUD, ("EVENT-SCAN DONE: Current Time = %ld\n", kalGetTimeTick()));
+
+    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.\n"));
+    }
+    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;
+
+            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 */
+
+            break;
+
+        case AIS_STATE_LOOKING_FOR:
+#if CFG_SUPPORT_ROAMING
+            eNextState = aisFsmRoamingScanResultsUpdate(prAdapter);
+#else
+            eNextState = AIS_STATE_SEARCH;
+#endif /* CFG_SUPPORT_ROAMING */
+            break;
+
+        default:
+            break;
+
+        }
+    }
+
+    if (eNextState != prAisFsmInfo->eCurrentState) {
+        aisFsmSteps(prAdapter, eNextState);
+    }
+
+    return;
+} /* 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, LOUD, ("EVENT-ABORT: Current State %s\n",
+        apucDebugAisState[prAisFsmInfo->eCurrentState]));
+#else
+    DBGLOG(AIS, LOUD, ("[%d] EVENT-ABORT: Current State [%d]\n",
+        DBG_AIS_IDX,
+           prAisFsmInfo->eCurrentState));
+#endif
+
+    //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;
+    }
+
+    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);
+    }
+
+    return;
+} /* 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;
+
+    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;
+        }
+        else {
+            /* Do abort NORMAL_TR */
+            aisFsmStateAbort_NORMAL_TR(prAdapter);
+        }
+    }
+
+    aisFsmDisconnect(prAdapter, fgDelayIndication);
+
+    return;
+
+} /* 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;
+
+    DEBUGFUNC("aisFsmRunEventJoinComplete()");
+
+    ASSERT(prMsgHdr);
+
+    prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo);
+    prJoinCompMsg = (P_MSG_JOIN_COMP_T)prMsgHdr;
+    prStaRec = prJoinCompMsg->prStaRec;
+    prAssocRspSwRfb = prJoinCompMsg->prSwRfb;
+
+    eNextState = prAisFsmInfo->eCurrentState;
+
+    // Check State and SEQ NUM
+    if (prAisFsmInfo->eCurrentState == AIS_STATE_JOIN) {
+        P_BSS_INFO_T prAisBssInfo;
+
+        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);
+                }
+
+#if CFG_SUPPORT_ROAMING
+                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);
+
+                    ASSERT(prBssDesc);
+                    ASSERT(prBssDesc->fgIsConnecting);
+
+                    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 {
+                        // abort connection trial
+                        prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued = FALSE;
+
+                        kalIndicateStatusAndComplete(prAdapter->prGlueInfo,
+                                 WLAN_STATUS_CONNECT_INDICATION,
+                                 NULL,
+                                 0);
+                      
+                        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);
+    }
+
+    if (prAssocRspSwRfb) {
+        nicRxReturnRFB(prAdapter, prAssocRspSwRfb);
+    }
+
+    cnmMemFree(prAdapter, prMsgHdr);
+
+    return;
+} /* 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);
+
+    return;
+} /* 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.
+            if ((prBssDesc = scanSearchBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID)) != 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);
+
+    return;
+} /* 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.
+            if ((prBssDesc = scanSearchBssDescByTA(prAdapter, prStaRec->aucMacAddr)) != 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.
+            if ((prBssDesc = scanSearchBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID)) != 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);
+    }
+
+    return;
+} /* 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));
+    }
+
+    return;
+} /* 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,
+    UINT_32 u4Param
+    )
+{
+    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;
+
+    //4 <3> Indicate Disconnected Event to Host immediately.
+    aisIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED, FALSE);
+
+    return;
+} /* 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, INFO, ("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;
+    }
+
+    //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;
+
+        //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
+
+    return;
+} /* 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) {
+
+        prAisBssInfo->ucPhyTypeSet =
+            prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11BGN; /* Depend on eBand */
+
+        prAisBssInfo->ucConfigAdHocAPMode = AD_HOC_MODE_MIXED_11BG; /* Depend on eCurrentOPMode and ucPhyTypeSet */
+    }
+    else {
+
+        prAisBssInfo->ucPhyTypeSet =
+            prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11AN; /* Depend on eBand */
+
+        prAisBssInfo->ucConfigAdHocAPMode = AD_HOC_MODE_11A; /* Depend on eCurrentOPMode and ucPhyTypeSet */
+    }
+
+    //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;
+
+    return;
+} /* 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)((UINT_32)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) {
+
+        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) {
+                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.
+    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);
+
+    return;
+} /* end of aisFsmDisconnect() */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @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,
+    UINT_32 u4Param
+    )
+{
+    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 = %ld\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);
+    }
+
+    return;
+} /* 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,
+    UINT_32 u4Param
+    )
+{
+    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);
+    }
+
+    return;
+} /* 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,
+    UINT_32 u4Param
+    )
+{
+    P_AIS_FSM_INFO_T prAisFsmInfo;
+    ENUM_AIS_STATE_T eNextState;
+
+    DEBUGFUNC("aisFsmRunEventJoinTimeout()");
+
+    prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo);
+    eNextState = prAisFsmInfo->eCurrentState;
+
+    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->prTargetStaRec->ucJoinFailureCount++;
+// For JB nl802.11
+#if 0
+        if(prAisFsmInfo->prTargetStaRec->ucJoinFailureCount < JOIN_MAX_RETRY_FAILURE_COUNT) {
+            /* 3.1 Retreat to AIS_STATE_SEARCH state for next try */
+            eNextState = AIS_STATE_SEARCH;
+        }
+        else {
+            /* 3.2 Retreat to AIS_STATE_WAIT_FOR_NEXT_SCAN state for next try */
+            eNextState = AIS_STATE_WAIT_FOR_NEXT_SCAN;
+        }
+#endif
+        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);
+    }
+
+    return;
+} /* end of aisFsmRunEventJoinTimeout() */
+
+
+#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);
+
+    return;
+}
+#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;
+                       if(NULL !=pucIe)
+            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));
+    }
+
+    return;
+} /* 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 { /* mismatched grant */
+        /* 2. return channel privilege to CNM immediately */
+        aisFsmReleaseCh(prAdapter);
+    }
+
+    return;
+} /* 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);
+    }
+
+    return;
+} /* 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) {
+        aisFsmStateAbort(prAdapter, DISCONNECT_REASON_CODE_RADIO_LOST, TRUE);
+    }
+
+    return;
+} /* end of aisBssBeaconTimeout() */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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(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;
+
+    /* 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);
+    }
+
+    return;
+} /* 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 */
+
+    return;
+} /* 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);
+
+    return;
+} /* 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);
+    }
+
+    return;
+}
+
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/assoc.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/assoc.c
new file mode 100755 (executable)
index 0000000..d91d197
--- /dev/null
@@ -0,0 +1,2050 @@
+/*
+** $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 recieve a assoc response frame but no p2p fucntion.
+ *
+ * 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 Microsoft 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_SUPPORT_WAPI
+    { (ELEM_HDR_LEN + ELEM_MAX_LEN_WAPI),   NULL,    wapiGenerateWAPIIE },   /* 68 */
+#endif
+#if CFG_RSN_MIGRATION
+    { (ELEM_HDR_LEN + ELEM_MAX_LEN_WPA),   NULL,        rsnGenerateWPAIE },     /* 221 */
+#endif
+    { (ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP),   NULL,    rlmReqGenerateExtCapIE },  /* 127 */
+    { (ELEM_HDR_LEN + ELEM_MAX_LEN_WMM_INFO),   NULL,   mqmGenerateWmmInfoIE },  /* 221 */
+#if CFG_RSN_MIGRATION
+    { (ELEM_HDR_LEN + ELEM_MAX_LEN_RSN),   NULL,        rsnGenerateRSNIE },    /* 48 */
+#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
+*/
+/*----------------------------------------------------------------------------*/
+__KAL_INLINE__ UINT_16
+assocBuildCapabilityInfo (
+    IN P_ADAPTER_T prAdapter,
+    IN P_STA_RECORD_T prStaRec
+    )
+{
+    UINT_32 u4NonHTPhyType;
+    UINT_16 u2CapInfo;
+
+
+    ASSERT(prStaRec);
+
+
+    /* Set up our requested capabilities. */
+    u2CapInfo = CAP_INFO_ESS;
+    u2CapInfo |= CAP_CF_STA_NOT_POLLABLE;
+
+    if (prStaRec->u2CapInfo & CAP_INFO_PRIVACY) {
+        u2CapInfo |= CAP_INFO_PRIVACY;
+    }
+
+
+    /* 7.3.1.4 */
+    if (prStaRec->fgHasBasicPhyType) {
+        u4NonHTPhyType = prStaRec->ucNonHTBasicPhyType;
+
+        if ( (rNonHTPhyAttributes[u4NonHTPhyType].fgIsShortPreambleOptionImplemented) &&
+            ( (prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_SHORT) || /* Short Preamble Option Enable is TRUE */
+             ((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 (rNonHTPhyAttributes[u4NonHTPhyType].fgIsShortSlotTimeOptionImplemented &&
+            prAdapter->rWifiVar.fgIsShortSlotTimeOptionEnable) {
+            u2CapInfo |= CAP_INFO_SHORT_SLOT_TIME;
+        }
+    }
+
+    DBGLOG(SAA, LOUD, ("ASSOC REQ: Compose Capability = 0x%04x for Target BSS ["MACSTR"].\n",
+        u2CapInfo, MAC2STR(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)
+*/
+/*----------------------------------------------------------------------------*/
+__KAL_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)((UINT_32)prMsduInfo->prPacket +
+                          (UINT_32)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 {
+        /* 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);
+        }
+    }
+
+    return;
+} /* 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)
+*/
+/*----------------------------------------------------------------------------*/
+__KAL_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);
+    }
+
+    return;
+} /* 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 */
+    if ( (prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen)) == 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)((UINT_32)(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)((UINT_32)(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)((UINT_32)(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.
+    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)Assocation Resp Frame.
+    prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) prSwRfb->pvHeader;
+
+    //4 <2> Parse the Header of (Re)Assocation 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)Assocation 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)((UINT_32)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)
+*/
+/*----------------------------------------------------------------------------*/
+__KAL_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);
+
+    return;
+} /* 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 */
+    if ( (prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen)) == 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)((UINT_32)(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)((UINT_32)(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 ["MACSTR"]\n",
+            MAC2STR(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;
+            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)) {
+                        if (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;
+            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 = 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)
+*/
+/*----------------------------------------------------------------------------*/
+__KAL_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)((UINT_32)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);
+    }
+
+    return;
+} /* 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)
+*/
+/*----------------------------------------------------------------------------*/
+__KAL_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);
+
+    return;
+} /* 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 */
+    if ( (prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen)) == 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)((UINT_32)(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.
+    nicTxEnqueueMsdu(prAdapter, prMsduInfo);
+
+    return WLAN_STATUS_SUCCESS;
+
+} /* end of assocSendReAssocRespFrame() */
+#endif /* CFG_SUPPORT_AAA */
+
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/auth.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/auth.c
new file mode 100755 (executable)
index 0000000..9938ebc
--- /dev/null
@@ -0,0 +1,1350 @@
+/*
+** $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)
+*/
+/*----------------------------------------------------------------------------*/
+__KAL_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
+
+    return;
+} /* 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(((UINT_32)(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 */
+    if ( (prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen)) == 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)((UINT_32)(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 */
+    if ( (prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen)) == 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)((UINT_32)(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.
+    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, LOUD, ("Discard Auth frame with auth type = %d, current = %d\n",
+            u2RxAuthAlgNum, prStaRec->ucAuthAlgNum));
+        return WLAN_STATUS_FAILURE;
+    }
+
+    //WLAN_GET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo, &u2RxTransactionSeqNum);
+    u2RxTransactionSeqNum = prAuthFrame->u2AuthTransSeqNo; // NOTE(Kevin): Optimized for ARM
+    if (u2RxTransactionSeqNum != u2TransactionSeqNum) {
+        DBGLOG(SAA, LOUD, ("Discard Auth frame with Transaction Seq No = %d\n",
+            u2RxTransactionSeqNum));
+        return WLAN_STATUS_FAILURE;
+    }
+
+    //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;
+        }
+
+        if ( ( prStaRec->prChallengeText = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, IE_SIZE(prIEHdr)) ) == 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)
+*/
+/*----------------------------------------------------------------------------*/
+__KAL_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
+
+    return;
+} /* 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 */
+    if ( (prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen)) == 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 {
+            return WLAN_STATUS_FAILURE;
+        }
+    }
+
+#endif
+
+    //4 <6> compose Deauthentication frame header and some fixed fields */
+    authComposeDeauthFrameHeaderAndFF(
+            (PUINT_8)((UINT_32)(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)((UINT_32)(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;
+
+    //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 ["MACSTR"]\n",
+            MAC2STR(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> 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/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/bss.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/bss.c
new file mode 100755 (executable)
index 0000000..263f18b
--- /dev/null
@@ -0,0 +1,2776 @@
+/*
+** $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 $
+** 
+** 08 29 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) Chnage 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 occured
+ *
+ * 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
+ * Seperate 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 Microsoft os query
+ * adding the wpa-none for ibss beacon.
+ *
+ * 04 15 2010 wh.su
+ * [BORA00000680][MT6620] Support the statistic for Microsoft 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 */
+#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->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 (!((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, INFO, ("Ignore the HT Bit for TKIP as pairwise cipher configed!\n"));
+               prStaRec->ucPhyTypeSet &= ~PHY_TYPE_BIT_HT;
+       }
+
+    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 */
+    if ( (prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen)) == 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)((UINT_32)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 */
+    if ( (prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen)) == 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)((UINT_32)(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)((UINT_32)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);
+    }
+
+    return;
+} /* 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)((UINT_32)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;
+    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) {
+                //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;
+            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 = prBssInfo->ucDTIMPeriod;
+            TIM_IE(pucBuffer)->ucBitmapControl = 0/*ucBitmapControl | (UINT_8)u4N1*/; // will be overwrite by FW
+
+            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.
+             */
+        }
+
+
+
+    }
+
+    return;
+} /* 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
+
+    return;
+} /* 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(INIT, 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)((UINT_32)(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;
+
+    if ( (prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen)) == 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)((UINT_32)(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)((UINT_32)(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)) {
+
+            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) {
+
+                    if (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 */) {
+                    if (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) {
+                /* 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);
+    }
+
+    return;
+} /* 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["MACSTR"]\n",
+                    MAC2STR(prStaRec->aucMacAddr)));
+                return;
+            }
+        }
+    }
+
+    LINK_INSERT_TAIL(prStaRecOfClientList, &prStaRec->rLinkEntry);
+
+    return;
+} /* 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 (!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;
+            }
+        }
+    }
+
+    DBGLOG(BSS, INFO, ("Current Client List didn't contain that STA_RECORD_T["MACSTR"] before removing.\n",
+        MAC2STR(prStaRec->aucMacAddr)));
+
+    return;
+} /* end of bssRemoveStaRecFromClientList() */
+#endif /* CFG_SUPPORT_ADHOC || CFG_SUPPORT_AAA */
+
+
+#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: "MACSTR" - Unsupported Phy.\n",
+                     MAC2STR(prBssDesc->aucSrcAddr)));
+
+                break;
+            }
+
+            if (prBssDesc->fgIsUnknownBssBasicRate) {
+                DBGLOG(BSS, LOUD,
+                    ("IBSS MERGE: Ignore Peer MAC: "MACSTR" - Unknown Basic Rate.\n",
+                     MAC2STR(prBssDesc->aucSrcAddr)));
+
+                break;
+            }
+
+            if (ibssCheckCapabilityForAdHocMode(prAdapter, prBssDesc) == WLAN_STATUS_FAILURE) {
+                DBGLOG(BSS, LOUD,
+                    ("IBSS MERGE: Ignore Peer MAC: "MACSTR" - Capability is not matched.\n",
+                     MAC2STR(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: "MACSTR" - Capability is not matched.\n",
+                     MAC2STR(prBssDesc->aucSrcAddr)));
+            }
+
+            return;
+        }
+
+        DBGLOG(BSS, LOUD,
+            ("IBSS MERGE: Peer MAC: "MACSTR" - Check capability was passed.\n",
+             MAC2STR(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);
+
+    }
+
+    return;
+} /* 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];
+
+    return;
+} /* 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 */
+
+
+    return;
+} /* 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;
+        }
+    }
+
+    return;
+} /* 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;
+
+
+            pucPartialVirtualBitmap = &prP2pSpecificBssInfo->aucPartialVirtualBitmap[(u2AssocId >> 3)]; // (u2AssocId / 8)
+            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;
+            }
+        }
+    }
+
+    return;
+} /* 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/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/cnm.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/cnm.c
new file mode 100755 (executable)
index 0000000..1af871d
--- /dev/null
@@ -0,0 +1,775 @@
+/*
+** $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 Microsoft 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
+    )
+{
+    return;
+} /* 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
+    )
+{
+    return;
+} /* 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);
+
+    return;
+} /* 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);
+
+    return;
+} /* 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;
+}
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @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;
+
+    /* 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;
+            }
+        }
+    }
+
+    return TRUE;
+}
+
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/cnm_mem.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/cnm_mem.c
new file mode 100755 (executable)
index 0000000..a1a50ba
--- /dev/null
@@ -0,0 +1,1292 @@
+/*
+** $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 DBG
+    if (prMsduInfo == NULL) {
+        DBGLOG(MEM, WARN, ("\n"));
+        DBGLOG(MEM, WARN, ("MgtDesc#=%ld\n", prQueList->u4NumElem));
+
+#if CFG_DBG_MGT_BUF
+        DBGLOG(MEM, WARN, ("rMgtBufInfo: alloc#=%ld, free#=%ld, null#=%ld\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);
+    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
+*/
+/*----------------------------------------------------------------------------*/
+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);
+
+    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;
+        }
+    }
+
+#ifdef LINUX
+    pvMemory = (PVOID)kalMemAlloc(u4Length, VIR_MEM_TYPE);
+#else
+    pvMemory = (PVOID)NULL;
+#endif
+
+#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;
+    }
+
+    /* Judge it belongs to which RAM type */
+    if ( ((UINT_32)pvMemory >= (UINT_32)&prAdapter->aucMsgBuf[0]) &&
+         ((UINT_32)pvMemory <= (UINT_32)&prAdapter->aucMsgBuf[MSG_BUFFER_SIZE-1])) {
+
+        prBufInfo = &prAdapter->rMsgBufInfo;
+        u4BlockIndex = ((UINT_32)pvMemory - (UINT_32)prBufInfo->pucBuf)
+                       >> MSG_BUF_BLOCK_SIZE_IN_POWER_OF_2;
+        ASSERT(u4BlockIndex < MAX_NUM_OF_BUF_BLOCKS);
+        eRamType = RAM_TYPE_MSG;
+    }
+    else if ( ((UINT_32)pvMemory >= (UINT_32)prAdapter->pucMgtBufCached) &&
+              ((UINT_32)pvMemory <= ((UINT_32)prAdapter->pucMgtBufCached + MGT_BUFFER_SIZE -1))) {
+        prBufInfo = &prAdapter->rMgtBufInfo;
+        u4BlockIndex = ((UINT_32)pvMemory - (UINT_32)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;
+
+            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;
+
+    return;
+}
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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
+    return;
+}
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @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/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/cnm_timer.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/cnm_timer.c
new file mode 100755 (executable)
index 0000000..2e8a8d7
--- /dev/null
@@ -0,0 +1,531 @@
+/*
+** $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;
+    return;
+}
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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 */
+
+    return;
+}
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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 UINT_32                  u4Data
+    )
+{
+    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->u4Data             = u4Data;
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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);
+
+    return;
+}
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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;
+    UINT_32             u4TimeoutData;
+    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;
+            u4TimeoutData = prTimer->u4Data;
+
+            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, u4TimeoutData);
+                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/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/hem_mbox.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/hem_mbox.c
new file mode 100755 (executable)
index 0000000..278e5d7
--- /dev/null
@@ -0,0 +1,831 @@
+/*
+** $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")
+};
+/*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       },
+#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                     }
+};
+
+/*******************************************************************************
+*                                 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);
+
+    return;
+}
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/mib.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/mib.c
new file mode 100755 (executable)
index 0000000..270bdf9
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+** $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/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_assoc.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_assoc.c
new file mode 100755 (executable)
index 0000000..d03d833
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+** $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/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_bss.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_bss.c
new file mode 100755 (executable)
index 0000000..d9aa1a1
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+** $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/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_fsm.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_fsm.c
new file mode 100755 (executable)
index 0000000..7e050c5
--- /dev/null
@@ -0,0 +1,3436 @@
+/*
+** $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 automaticly 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 continous 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 continous memory demands
+ * separate kalMemAlloc() into virtually-continous and physically-continous 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 */
+#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;
+
+        cnmTimerInitTimer(prAdapter,
+                            &(prP2pFsmInfo->rP2pFsmTimeoutTimer),
+                            (PFN_MGMT_TIMEOUT_FUNC)p2pFsmRunEventFsmTimeout,
+                            (UINT_32)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);
+
+    return;
+} /* 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", 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) {
+            DBGLOG(P2P, STATE, ("TRANSITION: [%s] -> [%s]\n",
+                                apucDebugP2pState[prP2pFsmInfo->eCurrentState],
+                                apucDebugP2pState[eNextState]));
+
+            /* 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 {
+                ASSERT(prP2pFsmInfo->prTargetBss != NULL);
+
+                // 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) {
+
+                    if ((prP2pFsmInfo->prTargetBss = p2pFuncKeepOnConnection(prAdapter,
+                                                                                                    &prP2pFsmInfo->rConnReqInfo,
+                                                                                                    &prP2pFsmInfo->rChnlReqInfo,
+                                                                                                    &prP2pFsmInfo->rScanReqInfo)) == 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);
+    }
+
+    return;
+} /* 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);
+        }
+    } 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);
+
+            prChnlReqInfo->u8Cookie = prP2pChnlReqMsg->u8Cookie;  /* Cookie can only be assign after abort.(for indication) */
+            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);
+    }
+
+    return;
+} /* 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);
+    }
+
+    return;
+} /* 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);
+    }
+
+    return;
+} /* 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, &(prP2pFsmInfo->rP2pFsmTimeoutTimer));
+        }
+
+
+    } while (FALSE);
+
+    return;
+} /* 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 UINT_32 u4Param
+    )
+{
+    P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T)u4Param;
+
+    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:
+            {
+                p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE);
+            }
+            break;
+//        case P2P_STATE_GC_JOIN:
+//            break;
+        default:
+            break;
+        }
+
+    } while (FALSE);
+
+    return;
+} /* 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 :%ld \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 :%ld \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);
+            }
+
+            // 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. */
+                /* Becuase 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;
+            }
+            
+            /* 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);
+    }
+    
+    return;
+} /* 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);
+    }
+
+    return;
+} /* 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);
+    }
+
+    return;
+} /* 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"));
+
+               printk("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);
+
+            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;
+
+            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 ["MACSTR":"MACSTR"]\n",
+                        MAC2STR(prP2pBssInfo->prStaRecOfAP->aucMacAddr),
+                        MAC2STR(prDisconnMsg->aucTargetID)));
+                    break;
+                }
+
+                
+                kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, NULL, NULL, 0, 0);
+
+                /* 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: "MACSTR"\n", MAC2STR(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: "MACSTR"\n", MAC2STR(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);
+    }
+
+    return;
+} /* 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);
+    }
+
+    return;
+}
+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, TRACE, ("Deauth TX Done\n"));
+
+        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);
+
+        /**/
+        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, TRACE, ("Mgmt Frame TX Fail, Status:%d.\n", rTxDoneStatus));
+        }
+        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;
+
+    do {
+        ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL));
+
+        DBGLOG(P2P, TRACE, ("P2P Join Complete\n"));
+
+        prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo;
+
+        if (prP2pFsmInfo == NULL) {
+            break;
+        }
+        
+
+        prJoinInfo = &(prP2pFsmInfo->rJoinInfo);
+        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);
+
+#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);
+                    kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo,
+                                                                    &prP2pFsmInfo->rConnReqInfo,
+                                                                    prJoinInfo->aucIEBuf,
+                                                                    prJoinInfo->u4BufLength,
+                                                                    prStaRec->u2StatusCode);
+
+                }
+                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);
+                        }
+                        else {
+                            /* Sometime the GO is not ready to response auth. Connect it again*/
+                            prP2pFsmInfo->prTargetBss = NULL;
+                        }
+
+
+                    }
+
+                }
+            }
+        }
+
+        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); 
+            }
+        }
+
+    } while (FALSE);
+
+    if (prMsgHdr) {
+        cnmMemFree(prAdapter, prMsgHdr);
+    }
+
+    return;
+
+} /* 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 */
+
+
+
+
+#if 0
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#endif
+
+
+
+
+
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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_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);
+        }
+
+        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);
+
+                prP2pBssInfo->prStaRecOfAP = NULL;
+
+                p2pFuncDisconnect(prAdapter, prStaRec, FALSE, u2ReasonCode);
+            }
+            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. */
+                        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);
+
+    return;
+} /* 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;
+    UINT_16 u2ReasonCode = 0;
+
+    do {
+        ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL));
+
+        if (prStaRec == NULL) {
+            prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx);
+        }
+
+
+        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);
+                
+                prP2pBssInfo->prStaRecOfAP = NULL;
+
+                p2pFuncDisconnect(prAdapter, prStaRec, FALSE, prStaRec->u2ReasonCode);
+                
+            }
+            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. */
+                        p2pFuncDisconnect(prAdapter, prStaRec, FALSE, u2ReasonCode);
+
+                        break;
+                    }
+                }
+            }
+            break;
+        case OP_MODE_P2P_DEVICE:
+        default:
+            ASSERT(FALSE);
+            break;
+        }
+
+
+    } while (FALSE);
+
+    return;
+} /* 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);
+
+    return;
+} /* 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);
+
+            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);
+
+                
+            }
+        }
+    } while (FALSE);
+
+    return;
+} /* p2pFsmRunEventBeaconTimeout */
+
+
+
+
+#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, 
+                    prWfdCfgSettings->u4WfdState, 
+                    prWfdCfgSettings->u4WfdFlag, 
+                    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 (IS_STA_P2P_TYPE(prStaRec)) {
+            // 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 indiate 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);
+
+    return;
+} /* p2pRunEventAAATxFail */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @brief This function will indiate 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;
+
+        bssRemoveStaRecFromClientList(prAdapter, prP2pBssInfo, prStaRec);
+
+        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;
+        }
+
+        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 indiate 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;
+
+
+    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/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_func.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_func.c
new file mode 100755 (executable)
index 0000000..cd6f6e2
--- /dev/null
@@ -0,0 +1,3845 @@
+#include "precomp.h"
+
+#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 */                 // Status
+    ,{ (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 prefered 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;
+
+    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. */
+        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;
+
+                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;
+            }
+        case SCAN_CHANNEL_FULL:
+        case SCAN_CHANNEL_2G4:
+        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);
+
+    return;
+} /* 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);
+
+    return;
+} /* p2pFuncCancelScan */
+
+
+VOID
+p2pFuncSwitchOPMode (
+    IN P_ADAPTER_T prAdapter,
+    IN P_BSS_INFO_T prP2pBssInfo,
+    IN ENUM_OP_MODE_T eOpMode,
+    IN BOOLEAN fgSyncToFW
+    )
+{
+    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 " MACSTR " \n", MAC2STR(prP2pBssInfo->aucOwnMacAddr)));
+            DBGLOG(P2P, TRACE, ("The BSSID is changed to " MACSTR " \n", MAC2STR(prP2pBssInfo->aucBSSID)));
+
+            /* Update BSS INFO to FW. */
+            if ((fgSyncToFW) && (eOpMode != OP_MODE_ACCESS_POINT)) {
+                nicUpdateBss(prAdapter, NETWORK_TYPE_P2P_INDEX);
+            }
+        }
+
+    } while (FALSE);
+
+    return;
+} /* 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);
+
+        DBGLOG(P2P, TRACE, ("p2pFuncStartGO:\n"));
+
+        /* 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) {
+            prBssInfo->ucPhyTypeSet = (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11AN); /* Depend on eBand */
+            prBssInfo->ucConfigAdHocAPMode = AP_MODE_11A; /* Depend on eCurrentOPMode and ucPhyTypeSet */
+        }
+        else if (fgIsPureAP) {
+            prBssInfo->ucPhyTypeSet = (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11BGN); /* Depend on eBand */
+            prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; /* Depend on eCurrentOPMode and ucPhyTypeSet */
+        }
+        else {
+            prBssInfo->ucPhyTypeSet = (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11GN); /* Depend on eBand */
+            prBssInfo->ucConfigAdHocAPMode = AP_MODE_11G_P2P; /* Depend on eCurrentOPMode and ucPhyTypeSet */
+        }
+
+
+        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);
+
+        //4 <3.4> Setup BSSID
+        nicPmIndicateBssCreated(prAdapter, NETWORK_TYPE_P2P_INDEX);
+
+    } while (FALSE);
+
+    return;
+} /* 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;
+        }
+        else {
+            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);
+
+    return;
+} /* 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;
+        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);
+
+    return;
+} /* 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;
+    UINT_8 aucIEBuf[MAX_IE_LENGTH];
+
+    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)((UINT_32)prBcnMsduInfo->prPacket + MAC_TX_RESERVED_FIELD);
+
+        if (!pucNewBcnBody) {
+            /* Old body. */
+            pucNewBcnBody = prBcnUpdateInfo->pucBcnBody;
+            ASSERT(u4NewBodyLen == 0);
+            u4NewBodyLen = prBcnUpdateInfo->u4BcnBodyLen;
+        }
+        else {
+            prBcnUpdateInfo->u4BcnBodyLen = u4NewBodyLen;
+        }
+
+        /* Temp buffer body part. */
+        kalMemCopy(aucIEBuf, pucNewBcnBody, u4NewBodyLen);
+
+        if (pucNewBcnHdr) {
+            kalMemCopy(prBcnFrame, pucNewBcnHdr, u4NewHdrLen);
+            prBcnUpdateInfo->pucBcnHdr = (PUINT_8)prBcnFrame;
+            prBcnUpdateInfo->u4BcnHdrLen = u4NewHdrLen;
+        }
+
+        pucIEBuf = (PUINT_8)((UINT_32)prBcnUpdateInfo->pucBcnHdr + (UINT_32)prBcnUpdateInfo->u4BcnHdrLen);
+        kalMemCopy(pucIEBuf, aucIEBuf, u4NewBodyLen);
+        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 ((UINT_32)prCliStaRec == (UINT_32)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 ((UINT_32)prCliStaRec == (UINT_32)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);
+                
+                // 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);
+
+                }
+
+            }
+
+            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);
+
+    return;
+} /* 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;
+
+    DBGLOG(P2P, TRACE, ("p2pFuncDisconnect()"));
+
+    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);
+        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 */
+
+
+
+
+
+
+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;
+
+    do {
+        ASSERT_BREAK((prAdapter != NULL) && (prMgmtTxReqInfo != NULL));
+
+        if (prMgmtTxReqInfo->fgIsMgmtTxRequested) {
+
+            // 1. prMgmtTxReqInfo->prMgmtTxMsdu != NULL
+            /* Packet on driver, not done yet, drop it. */
+            if ((prTxMsduInfo = prMgmtTxReqInfo->prMgmtTxMsdu) != 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;
+            }
+
+            // 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)((UINT_32)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"));
+            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: "MACSTR" .\n", MAC2STR(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;
+        DBGLOG(P2P, TRACE, ("Mgmt seq NO. %d .\n", prMgmtTxMsdu->ucTxSeqNum));
+
+        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);
+
+    return;
+}
+/* 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
+
+    return;
+} /* 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, TRACE, ("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) {
+            /* 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);
+
+            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));
+            cnmStaRecFree(prAdapter, prStaRec, FALSE);
+            break;
+        }
+        else {
+            /* Hotspot Blacklist */
+            if(prAuthFrame->aucSrcAddr) {
+                if(kalP2PCmpBlackList(prAdapter->prGlueInfo, prAuthFrame->aucSrcAddr)) {
+                    fgReplyAuth = FALSE;
+                    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);
+
+    return;
+} /* 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;
+
+    ASSERT(prP2PConnSettings);
+
+    /* 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;
+
+    return;
+} /* 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
+
+
+    /* 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;
+        }
+        else {
+            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 becasue some API is not ready\n"); /* Eddie */
+        if (!prAdapter->rWifiVar.prP2pFsmInfo) {
+            fgReplyAssocResp = FALSE;
+            ASSERT(FALSE);
+            break;
+        }
+        
+        prWfdCfgSettings = &prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings;
+        DBGLOG(P2P, INFO,("Current WfdCfgSettings 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;
+            }
+            else {
+                
+                //UINT_16 u2AttriListLen = 0;
+                UINT_16 u2WfdDevInfo = 0;
+                P_WFD_DEVICE_INFORMATION_IE_T prAttriWfdDevInfo = (P_WFD_DEVICE_INFORMATION_IE_T)NULL;
+                
+                //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) {
+
+                    //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) {
+
+                        if((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 */
+
+
+                }
+                else {
+                    /* Without WFD IE. 
+                                     * Do nothing. Accept the connection request.
+                                     */
+                }
+            }
+
+        } /* 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) {
+
+                       printk("p2pFuncValidateProbeReq\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) {
+        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;
+    BOOL    ucNewSecMode = FALSE;
+    BOOL    ucOldSecMode = FALSE;
+
+    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"));
+
+                    /* Update when starting GO. */
+                    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:%lx, 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"));
+                {
+                    UINT_8 ucOuiType;
+                    UINT_16 u2SubTypeVersion;
+                    if (rsnParseCheckForWFAInfoElem(prAdapter, pucIE, &ucOuiType, &u2SubTypeVersion)) {
+                        if ((ucOuiType == VENDOR_OUI_TYPE_WPA) &&
+                                (u2SubTypeVersion == VERSION_WPA)) {
+                            kalP2PSetCipher(prAdapter->prGlueInfo, IW_AUTH_CIPHER_TKIP);
+                            ucNewSecMode = TRUE;
+                        }
+                        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);
+
+    return;
+} /* 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);
+
+
+    return;
+} /* 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%lx\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);
+
+    return;
+}   /* 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%lx\n", prAdapter->u4OsPacketFilter));
+        }
+        
+    } while (FALSE);
+
+    
+
+    
+    return;
+} /* 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);
+
+    return;
+} /* 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;
+    
+    do {
+        ASSERT_BREAK((prAdapter != NULL) && 
+                        (pucIE != NULL) &&
+                        (u2IELength != 0) &&
+                        (ppucAttriList != NULL) &&
+                        (pu2AttriListLen != NULL));
+
+        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));
+            break;
+        }
+
+
+        IE_FOR_EACH(pucIE, u2IELength, u2Offset) {
+            if (ELEM_ID_VENDOR == IE_ID(pucIE)) {
+                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);
+                        }
+                    }
+                    else {
+/* More than 2 attributes. */
+                        UINT_16 u2CopyLen;
+
+                        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)((UINT_32)pucAttriListStart + (UINT_32)u2AttriListLen), 
+                                        &prIe->aucP2PAttributes[0],
+                                        u2CopyLen);
+                            
+                            u2AttriListLen += u2CopyLen;
+                        }
+                        
+                    
+                    }
+                } /* prIe->aucOui */
+            } /* ELEM_ID_VENDOR */
+        } /* IE_FOR_EACH */
+
+       
+    } while (FALSE);
+
+    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) {
+        }
+        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);
+    
+        *ppucAttriList = pucAttriListStart;
+        *pu2AttriListLen = u2AttriListLen;
+    
+    }
+    else {
+        *ppucAttriList = (PUINT_8)NULL;
+        *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;
+
+
+    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)((UINT_32)prMgmtTxMsdu->prPacket + MAC_TX_RESERVED_FIELD);
+        ASSERT_BREAK((prProbeRspFrame->u2FrameCtrl & MASK_FRAME_TYPE) == MAC_FRAME_PROBE_RSP);
+
+        //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:
+                {
+                    UINT_8 ucOuiType = 0;
+                    UINT_16 u2SubTypeVersion = 0;
+#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);
+        }
+
+#if CFG_SUPPORT_WFD
+         u2EstimatedExtraIELen += prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen;
+#endif   
+      
+
+
+        if ((u2EstimateSize += u2EstimatedExtraIELen) > (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)((UINT_32)(prRetMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD),
+                                                        prProbeRspFrame->aucDestAddr,
+                                                        prProbeRspFrame->aucSrcAddr,
+                                                        prProbeRspFrame->aucBSSID,
+                                                        prProbeRspFrame->u2BeaconInterval,
+                                                        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)((UINT_32)prRetMsduInfo->prPacket + (UINT_32)prRetMsduInfo->u2FrameLength));
+
+            prRetMsduInfo->u2FrameLength += (UINT_16)kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 2);
+        }
+
+        if (fgIsP2PIE) {
+            kalP2PGenWSC_IE(prAdapter->prGlueInfo,
+                                1,
+                                (PUINT_8)((UINT_32)prRetMsduInfo->prPacket + (UINT_32)prRetMsduInfo->u2FrameLength));
+
+            prRetMsduInfo->u2FrameLength += (UINT_16)kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 1);
+        }
+
+#if CFG_SUPPORT_WFD
+        if(prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen>0) {
+            kalMemCopy((PUINT_8)((UINT_32)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);
+
+    return;
+} /* 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)((UINT_32)prMsduInfo->prPacket + (UINT_32)prMsduInfo->u2FrameLength);
+
+        kalMemCopy(pucIEBuf, prP2pSpeBssInfo->aucAttributesCache, prP2pSpeBssInfo->u2AttributeLen);
+
+        prMsduInfo->u2FrameLength += prP2pSpeBssInfo->u2AttributeLen;
+
+    } while (FALSE);
+
+    return;
+} /* 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)((UINT_32)prMsduInfo->prPacket +
+                          (UINT_32)prMsduInfo->u2FrameLength);
+
+    ASSERT(pucBuffer);
+
+    // TODO: Check P2P FSM State.
+    kalP2PGenWSC_IE(prAdapter->prGlueInfo,
+                   0,
+                   pucBuffer);
+
+    prMsduInfo->u2FrameLength += u2IELen;
+
+    return;
+} /* 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 (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)((UINT_32)prMsduInfo->prPacket +
+                          (UINT_32)prMsduInfo->u2FrameLength);
+
+    ASSERT(pucBuffer);
+
+    // TODO: Check P2P FSM State.
+    kalP2PGenWSC_IE(prAdapter->prGlueInfo,
+                   0,
+                   pucBuffer);
+
+    prMsduInfo->u2FrameLength += u2IELen;
+
+    return;
+} 
+/* 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)((UINT_32)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)((UINT_32)prIeP2P + (VENDOR_OUI_TYPE_LEN + P2P_MAXIMUM_ATTRIBUTE_LEN));
+
+                    prIeP2P = (P_IE_P2P_T)((UINT_32)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);
+
+    return;
+} /* 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)((UINT_32)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)((UINT_32)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;
+                }
+                else {
+                    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));
+
+    do {
+        ASSERT_BREAK((prAdapter != NULL) 
+                && (pucIEBuf != NULL));
+
+        u2BufferLenLeft = u2BufferLen;
+        pucIE = pucIEBuf;
+        do {
+            fgIsMore = FALSE;
+            prP2pIE = (P_IE_P2P_T)p2pFuncGetSpecIE(prAdapter,
+                                            pucIE,
+                                            u2BufferLenLeft,
+                                            ELEM_ID_VENDOR,
+                                            &fgIsMore);
+
+            if (prP2pIE) {
+
+                ASSERT(prP2pIE>pucIE);
+
+                u2BufferLenLeft = u2BufferLen - (UINT_16)(  ((UINT_32)prP2pIE) - ((UINT_32)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) {
+
+                if (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]) 
+                                ) {
+
+                            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;
+                                }
+
+                            }
+
+                        }
+                            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;
+                                    }
+                     
+                        }
+                    }
+                            else {
+                                // Possible or else.
+                }
+
+            }
+                    } /* ucOuiType */
+                } /* P2P_OUI_TYPE_LEN */ 
+            
+                pucIE = (PUINT_8)(((UINT_32)prP2pIE) + IE_SIZE(prP2pIE));
+
+            } /* prP2pIE */
+                
+        } while (prP2pIE && fgIsMore && u2BufferLenLeft);
+
+    } while (FALSE);
+
+    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)((UINT_32)(prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD);
+
+        kalMemCopy(pucBuffer, pucBcnBuffer, u4BcnBufLen);
+
+        prMsduInfo->fgIs802_11 = TRUE;
+        prMsduInfo->u2FrameLength = (UINT_16)u4BcnBufLen;
+
+        if (fgSynToFW) {
+            rWlanStatus = p2pFuncGenerateBeaconProbeRsp(prAdapter, prP2pBssInfo, prMsduInfo, fgIsProbeRsp);
+        }
+
+    } while (FALSE);
+
+    return rWlanStatus;
+
+} /* p2pFuncComposeBeaconTemplate */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_ie.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_ie.c
new file mode 100755 (executable)
index 0000000..33cafca
--- /dev/null
@@ -0,0 +1,582 @@
+#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)((UINT_32)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)((UINT_32)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)((UINT_32)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)((UINT_32)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)((UINT_32)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)((UINT_32)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)((UINT_32)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)((UINT_32)prIeWFD + (WFD_IE_OUI_HDR + P2P_MAXIMUM_ATTRIBUTE_LEN));
+
+                    prIeWFD = (P_IE_WFD_T)((UINT_32)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);
+
+    return;
+} /* 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 (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 */
+
+#endif
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_rlm.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_rlm.c
new file mode 100755 (executable)
index 0000000..a01e1ca
--- /dev/null
@@ -0,0 +1,1018 @@
+/*
+** $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"
+
+extern VOID
+rlmSyncOperationParams (
+    P_ADAPTER_T         prAdapter,
+    P_BSS_INFO_T        prBssInfo
+    );
+
+/*******************************************************************************
+*                              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;
+
+    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 */
+                if (eHtProtectMode == HT_PROTECT_MODE_NONE) {
+                    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);
+        }
+    }
+
+    /* 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)((UINT_32)prChannelEntryField +
+                                                                                    P2P_ATTRI_LEN_CHANNEL_ENTRY +
+                                                                                    (UINT_32)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 deivce 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
+    return;
+} /* 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];
+    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)((UINT_32)prChannelEntryIII +
+                                                                                P2P_ATTRI_LEN_CHANNEL_ENTRY +
+                                                                                (UINT_32)prChannelEntryIII->ucNumberOfChannels);
+                }
+
+                ucOriChnlSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryI->ucNumberOfChannels);
+
+                prChannelEntryI = (P_CHANNEL_ENTRY_FIELD_T)((UINT_32)prChannelEntryI +
+                                                                                P2P_ATTRI_LEN_CHANNEL_ENTRY +
+                                                                                (UINT_32)prChannelEntryI->ucNumberOfChannels);
+
+
+            }
+
+
+            ucChannelListSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryII->ucNumberOfChannels);
+
+            prChannelEntryII = (P_CHANNEL_ENTRY_FIELD_T)((UINT_32)prChannelEntryII +
+                                                                                P2P_ATTRI_LEN_CHANNEL_ENTRY +
+                                                                                (UINT_32)prChannelEntryII->ucNumberOfChannels);
+
+
+        }
+
+
+        kalMemCopy(prP2pConnSetting->aucChannelEntriesField, aucCommonChannelList, ucNewChnlSize);
+        prP2pConnSetting->ucRfChannelListSize = ucNewChnlSize;
+
+    } while (FALSE);
+
+    return;
+} /* 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
+            }
+            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);
+            }
+
+        }
+
+
+    } 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)((UINT_32)prChannelEntry +
+                                                                                                P2P_ATTRI_LEN_CHANNEL_ENTRY +
+                                                                                                (UINT_32)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/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_rlm_obss.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_rlm_obss.c
new file mode 100755 (executable)
index 0000000..f904537
--- /dev/null
@@ -0,0 +1,374 @@
+/*
+** $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/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_scan.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_scan.c
new file mode 100755 (executable)
index 0000000..0639b53
--- /dev/null
@@ -0,0 +1,831 @@
+/*
+** $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;
+        }
+    }
+
+    return;
+} /* 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));
+        }
+    }
+
+    return;
+} /* 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
+    )
+{
+    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;
+
+    if (prBssDesc->fgIsP2PPresent) {
+
+        if ((!prP2pBssInfo->ucDTIMPeriod) &&          // First time.
+            (prP2pBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) &&     // P2P GC
+                (prP2pBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) &&   // Connected
+                ((prWlanBeaconFrame->u2FrameCtrl & MASK_FRAME_TYPE) == MAC_FRAME_BEACON) &&  // TX Beacon
+                EQUAL_SSID(prBssDesc->aucSSID,                                                                  // SSID Match
+                            prBssDesc->ucSSIDLen,
+                            prP2pConnSettings->aucSSID,
+                            prP2pConnSettings->ucSSIDLen)) {
+
+
+            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. */
+                break;
+            }
+
+            rChannelInfo.ucChannelNum = prBssDesc->ucChannelNum;
+            rChannelInfo.eBand = prBssDesc->eBand;
+
+            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);
+
+    return;
+} /* 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
+    )
+{
+
+    return;
+} /* 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: "MACSTR"\n", MAC2STR(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: "MACSTR"\n", MAC2STR(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: "MACSTR"\n", MAC2STR(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;
+            }
+
+            /* Final decision. */
+            prCandidateBssDesc = prBssDesc;
+            break;
+        }
+
+
+
+    } while (FALSE);
+
+    return prCandidateBssDesc;
+} /* scanP2pSearchDesc */
+
+
+
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_state.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/p2p_state.c
new file mode 100755 (executable)
index 0000000..64b9ae6
--- /dev/null
@@ -0,0 +1,577 @@
+#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;
+            *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, &(prP2pFsmInfo->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, &(prP2pFsmInfo->rP2pFsmTimeoutTimer));
+
+    } while (FALSE);
+
+    return;
+} /* 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"));
+        cnmTimerStartTimer(prAdapter,
+                        &(prP2pFsmInfo->rP2pFsmTimeoutTimer),
+                        prChnlReqInfo->u4MaxInterval);
+
+        kalP2PIndicateChannelReady(prAdapter->prGlueInfo,
+                            prChnlReqInfo->u8Cookie,
+                            prChnlReqInfo->ucReqChnlNum,
+                            prChnlReqInfo->eBand,
+                            prChnlReqInfo->eChnlSco,
+                            prChnlReqInfo->u4MaxInterval);
+
+    } while (FALSE);
+
+    return;
+} /* 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, &(prP2pFsmInfo->rP2pFsmTimeoutTimer));
+
+        /* Restore the original channel info. */
+        prP2pBssInfo->ucPrimaryChannel = prChnlReqInfo->ucOriChnlNum;
+        prP2pBssInfo->eBand = prChnlReqInfo->eOriBand;
+        prP2pBssInfo->eBssSCO = prChnlReqInfo->eOriChnlSco;
+
+        if (eNextState != P2P_STATE_CHNL_ON_HAND) {
+            /* Indicate channel return. */
+            kalP2PIndicateChannelExpired(prAdapter->prGlueInfo, &prP2pFsmInfo->rChnlReqInfo);
+
+            // Return Channel.
+            p2pFuncReleaseCh(prAdapter, &(prP2pFsmInfo->rChnlReqInfo));
+        }
+
+    } while (FALSE);
+    return;
+} /* 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);
+
+    return;
+} /* 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);
+
+    return;
+} /* 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;
+
+                if ((ucPreferedChnl = prP2pConnSettings->ucOperatingChnl) == 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;
+            prChnlReqInfo->ucReqChnlNum = prP2pSpecificBssInfo->ucPreferredChannel = ucPreferedChnl;
+            prChnlReqInfo->eBand = prP2pSpecificBssInfo->eRfBand = eBand;
+            prChnlReqInfo->eChnlSco = prP2pSpecificBssInfo->eRfSco = eSco;
+        }
+        else {
+            p2pFuncCancelScan(prAdapter, &(prP2pFsmInfo->rScanReqInfo));
+        }
+
+
+    } while (FALSE);
+
+    return;
+} /* 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);
+    return;
+} /* 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);
+
+    return;
+} /* 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,
+                            &(prP2pFsmInfo->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);
+
+    return;
+} /* 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, &(prP2pFsmInfo->rP2pFsmTimeoutTimer));
+
+        /* Release channel requested. */
+        p2pFuncReleaseCh(prAdapter, &(prP2pFsmInfo->rChnlReqInfo));
+
+    } while (FALSE);
+
+    return;
+
+} /* p2pStateAbort_GC_JOIN */
+
+
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/privacy.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/privacy.c
new file mode 100755 (executable)
index 0000000..66b33a6
--- /dev/null
@@ -0,0 +1,1024 @@
+/*
+** $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 Microsoft os query
+ * remove the assert code for allow ad-hoc pkt.
+ *
+ * 04 13 2010 wh.su
+ * [BORA00000680][MT6620] Support the statistic for Microsoft 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,
+                   (UINT_32)NULL);
+
+#if CFG_SUPPORT_802_11W
+    cnmTimerInitTimer(prAdapter,
+                   &prAisSpecBssInfo->rSaQueryTimer,
+                   (PFN_MGMT_TIMEOUT_FUNC)rsnStartSaQueryTimer,
+                   (UINT_32)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
+*/
+/*----------------------------------------------------------------------------*/
+BOOL
+secCheckClassError (
+    IN P_ADAPTER_T          prAdapter,
+    IN P_SW_RFB_T           prSwRfb,
+    IN P_STA_RECORD_T       prStaRec
+    )
+{
+    ASSERT(prAdapter);
+    ASSERT(prSwRfb);
+    //ASSERT(prStaRec);
+
+    //prStaRec = &(g_arStaRec[prSwRfb->ucStaRecIdx]);
+
+    if ((prStaRec) && 1 /* RXM_IS_DATA_FRAME(prSwRfb) */) {
+        ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex = prStaRec->ucNetTypeIndex;
+
+        if (IS_NET_ACTIVE(prAdapter, eNetTypeIndex)) {
+                 P_BSS_INFO_T prBssInfo;
+                 prBssInfo = &prAdapter->rWifiVar.arBssInfo[eNetTypeIndex];            
+
+            if ((STA_STATE_3 != prStaRec->ucStaState) &&
+                  IS_BSS_ACTIVE(prBssInfo) && 
+                  prBssInfo->fgIsNetAbsent == FALSE) {
+                /*(IS_AP_STA(prStaRec) || IS_CLIENT_STA(prStaRec))) {*/                
+
+                if (WLAN_STATUS_SUCCESS == authSendDeauthFrame(prAdapter,
+                                                               prStaRec,
+                                                               NULL,
+                                                               REASON_CODE_CLASS_3_ERR,
+                                                               (PFN_TX_DONE_HANDLER)NULL)) {
+
+                    DBGLOG(RSN, INFO, ("Send Deauth to MAC:["MACSTR"] for Rx Class 3 Error.\n",
+                                      MAC2STR(prStaRec->aucMacAddr)));
+                }
+
+                return FALSE;
+            }
+
+            return secRxPortControlCheck(prAdapter, prSwRfb);
+        }
+    }
+
+    return FALSE;
+} /* 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 "MACSTR" port %s\n", MAC2STR(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
+*
+*/
+/*----------------------------------------------------------------------------*/
+BOOL /* 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(INIT, 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(INIT, 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
+*
+*/
+/*----------------------------------------------------------------------------*/
+BOOL
+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;
+        }
+        else {
+            DBGLOG(RSN, LOUD, ("1x Protected.\n"));
+            return TRUE;
+        }
+    }
+    else {
+        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/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/rate.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/rate.c
new file mode 100755 (executable)
index 0000000..c63fe7b
--- /dev/null
@@ -0,0 +1,547 @@
+/*
+** $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)) {
+                    if ((afgIsOFDMRate[i] && afgIsOFDMRate[j]) || (!afgIsOFDMRate[i] && !afgIsOFDMRate[j])) // Reply ACK Frame at the same Modulation Scheme.
+                        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/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/rlm.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/rlm.c
new file mode 100755 (executable)
index 0000000..1954f88
--- /dev/null
@@ -0,0 +1,1723 @@
+/*
+** $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);
+}
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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);
+    }
+}
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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
+*/
+/*----------------------------------------------------------------------------*/
+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);
+
+    /* 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);
+    }
+
+    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);
+}
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief
+*
+* \param[in]
+*
+* \return none
+*/
+/*----------------------------------------------------------------------------*/
+static VOID
+rlmFillExtCapIE (
+    P_ADAPTER_T     prAdapter,
+    P_BSS_INFO_T    prBssInfo,
+    P_MSDU_INFO_T   prMsduInfo
+    )
+{
+    P_EXT_CAP_T     prExtCap;
+    BOOLEAN         fg40mAllowed;
+
+    ASSERT(prAdapter);
+    ASSERT(prMsduInfo);
+
+    fg40mAllowed = prBssInfo->fgAssoc40mBwAllowed;
+
+    /* Add Extended Capabilities IE */
+    prExtCap = (P_EXT_CAP_T)
+               (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength);
+
+    prExtCap->ucId = ELEM_ID_EXTENDED_CAP;
+    prExtCap->ucLength = 1;
+    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);
+}
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief
+*
+* \param[in]
+*
+* \return none
+*/
+/*----------------------------------------------------------------------------*/
+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);
+
+    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);
+}
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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 vaild 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_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
+        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;
+
+    ASSERT(prAdapter);
+    ASSERT(prBssInfo && prSwRfb);
+    ASSERT(pucIE);
+
+    /* 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
+    )
+{
+    ASSERT(prAdapter);
+    ASSERT(prBssInfo && prSwRfb);
+    ASSERT(pucIE);
+
+#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 procesed 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) {
+                /* To do: Ad-hoc */
+            }
+
+            /* Appy new parameters if necessary */
+            if (fgNewParameter) {
+                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;
+
+    if ((ucPriChannel =
+         rlmRecIeInfoForClient(prAdapter, prBssInfo, pucIE, u2IELength)) > 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()
+     */
+}
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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, INFO, ("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 */
+}
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/rlm_domain.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/rlm_domain.c
new file mode 100755 (executable)
index 0000000..b5f3438
--- /dev/null
@@ -0,0 +1,681 @@
+/*
+** $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 channle 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"
+
+/*******************************************************************************
+*                              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_US, COUNTRY_CODE_BS, COUNTRY_CODE_BB, COUNTRY_CODE_BO, COUNTRY_CODE_DM,
+    COUNTRY_CODE_DO, COUNTRY_CODE_HT, COUNTRY_CODE_PR, COUNTRY_CODE_TH, COUNTRY_CODE_TW,
+    COUNTRY_CODE_AI, COUNTRY_CODE_AG, COUNTRY_CODE_AW, COUNTRY_CODE_BM, COUNTRY_CODE_CU,
+    COUNTRY_CODE_GD, COUNTRY_CODE_GY, COUNTRY_CODE_JM, COUNTRY_CODE_KN, COUNTRY_CODE_LC,
+    COUNTRY_CODE_VC, COUNTRY_CODE_TT, COUNTRY_CODE_SR
+};
+static const UINT_16     g_u2CountryGroup1[] =
+{
+    COUNTRY_CODE_BR, COUNTRY_CODE_EC, COUNTRY_CODE_HK, COUNTRY_CODE_MX, COUNTRY_CODE_PE,
+    COUNTRY_CODE_CR, COUNTRY_CODE_MD, COUNTRY_CODE_NI, COUNTRY_CODE_PZ
+};
+static const UINT_16     g_u2CountryGroup2[] = {COUNTRY_CODE_CO, COUNTRY_CODE_PY};
+static const UINT_16     g_u2CountryGroup3[] = {COUNTRY_CODE_JP};
+static const UINT_16     g_u2CountryGroup4[] =
+{
+    COUNTRY_CODE_CN, COUNTRY_CODE_UY, COUNTRY_CODE_MA
+};
+static const UINT_16     g_u2CountryGroup5[] = {COUNTRY_CODE_AR};
+static const UINT_16     g_u2CountryGroup6[] = {COUNTRY_CODE_AU, COUNTRY_CODE_NZ};
+static const UINT_16     g_u2CountryGroup7[] = {COUNTRY_CODE_RU};
+static const UINT_16     g_u2CountryGroup8[] =
+{
+    COUNTRY_CODE_ID, COUNTRY_CODE_HN, COUNTRY_CODE_PG, COUNTRY_CODE_PK
+};
+static const UINT_16     g_u2CountryGroup9[] = {COUNTRY_CODE_CA};
+static const UINT_16     g_u2CountryGroup10[] =
+{
+    COUNTRY_CODE_CL, COUNTRY_CODE_IN, COUNTRY_CODE_SA, COUNTRY_CODE_SG, COUNTRY_CODE_VE,
+    COUNTRY_CODE_MY, COUNTRY_CODE_VN, COUNTRY_CODE_EG
+};
+static const UINT_16     g_u2CountryGroup11[] = {COUNTRY_CODE_IL, COUNTRY_CODE_UA};
+static const UINT_16     g_u2CountryGroup12[] = {COUNTRY_CODE_JO, COUNTRY_CODE_KW};
+static const UINT_16     g_u2CountryGroup13[] = {COUNTRY_CODE_KR, COUNTRY_CODE_OM};
+static const UINT_16     g_u2CountryGroup14[] =
+{
+    COUNTRY_CODE_EU
+    /* When country code is not found, this domain info will be used.
+     * So mark all country codes to reduce search time. 20110908
+     */
+    /*, COUNTRY_CODE_PH, COUNTRY_CODE_TR, COUNTRY_CODE_IR, COUNTRY_CODE_BY,
+    COUNTRY_CODE_LK */
+};
+
+
+DOMAIN_INFO_ENTRY arSupportedRegDomains[] = {
+    {
+        (PUINT_16) g_u2CountryGroup0, sizeof(g_u2CountryGroup0) / 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_u2CountryGroup1, sizeof(g_u2CountryGroup1) / 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,  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_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,  FALSE }, /* CH_SET_UNII_MID_52_64 */
+            { 121, BAND_5G,  CHNL_SPAN_20, 100,  11,  FALSE }, /* 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_u2CountryGroup3, sizeof(g_u2CountryGroup3) / 2,
+        {
+            {  81, BAND_2G4, CHNL_SPAN_5,    1,  13,  FALSE }, /* CH_SET_2G4_1_14 */
+            {  82, BAND_2G4, CHNL_SPAN_5,   14,   1,  FALSE },
+
+            { 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_NULL,           0,   0,   0,  FALSE }  /* CH_SET_UNII_UPPER_NA */
+        }
+    },
+    {
+        (PUINT_16) g_u2CountryGroup4, sizeof(g_u2CountryGroup4) / 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_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_u2CountryGroup5, sizeof(g_u2CountryGroup5) / 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_5G,  CHNL_SPAN_20,  52,   4,  FALSE }, /* 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_u2CountryGroup6, sizeof(g_u2CountryGroup6) / 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,   4,  FALSE }, /* CH_SET_UNII_UPPER_149_161 */
+            {   0, BAND_NULL,           0,   0,   0,  FALSE }
+        }
+    },
+    {
+        (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,  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,   4,  FALSE }, /* CH_SET_UNII_UPPER_149_161 */
+            {   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_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_u2CountryGroup9, sizeof(g_u2CountryGroup9) / 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,   5,  FALSE }, /* CH_SET_UNII_WW_100_116_132_140 */
+            { 121, BAND_5G,  CHNL_SPAN_20, 132,   5,  FALSE },
+            { 125, BAND_5G,  CHNL_SPAN_20, 149,   5,  FALSE }, /* CH_SET_UNII_UPPER_149_165 */
+        }
+    },
+    {
+        (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,  FALSE }, /* 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_5G,  CHNL_SPAN_20,  52,   4,  FALSE }, /* 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_u2CountryGroup12, sizeof(g_u2CountryGroup12) / 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_u2CountryGroup13, sizeof(g_u2CountryGroup13) / 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,   5,  FALSE }, /* CH_SET_UNII_UPPER_149_165 */
+            {   0, BAND_NULL,           0,   0,   0,  FALSE }
+        }
+    },
+    {
+        /* Note: The final one is for Europe union now. */
+        (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,  11,  FALSE }, /* CH_SET_UNII_WW_100_140 */
+            { 125, BAND_5G,  CHNL_SPAN_20, 149,   7,  FALSE }, /* CH_SET_UNII_UPPER_149_173 */
+            {   0, BAND_NULL,           0,   0,   0,  FALSE }
+        }
+    }
+};
+
+#if 0
+COUNTRY_CH_SET_T arCountryChSets[] = {
+    /* idx=0: US, Bahamas, Barbados, Bolivia(Voluntary), Dominica (the Commonwealth of Dominica),
+       The Dominican Republic, Haiti */
+    {CH_SET_2G4_1_11,           CH_SET_UNII_LOW_36_48,          CH_SET_UNII_MID_52_64,
+     CH_SET_UNII_WW_100_140,    CH_SET_UNII_UPPER_149_165},
+    /* idx=1: Brazil, Ecuador, Hong Kong, Mexico, Peru */
+    {CH_SET_2G4_1_13,           CH_SET_UNII_LOW_36_48,          CH_SET_UNII_MID_52_64,
+     CH_SET_UNII_WW_100_140,    CH_SET_UNII_UPPER_149_165},
+    /* idx=2: JP1, Colombia(Voluntary), Paraguay */
+    {CH_SET_2G4_1_13,           CH_SET_UNII_LOW_36_48,          CH_SET_UNII_MID_52_64,
+     CH_SET_UNII_WW_100_140,    CH_SET_UNII_UPPER_NA},
+    /* idx=3: JP2 */
+    {CH_SET_2G4_1_14,           CH_SET_UNII_LOW_36_48,          CH_SET_UNII_MID_52_64,
+     CH_SET_UNII_WW_100_140,    CH_SET_UNII_UPPER_NA},
+    /* idx=4: CN, Uruguay, Morocco */
+    {CH_SET_2G4_1_13,           CH_SET_UNII_LOW_NA,             CH_SET_UNII_MID_NA,
+     CH_SET_UNII_WW_NA,         CH_SET_UNII_UPPER_149_165},
+    /* idx=5: Argentina */
+    {CH_SET_2G4_1_13,           CH_SET_UNII_LOW_NA,             CH_SET_UNII_MID_52_64,
+     CH_SET_UNII_WW_NA,         CH_SET_UNII_UPPER_149_165},
+    /* idx=6: Australia, New Zealand */
+    {CH_SET_2G4_1_11,           CH_SET_UNII_LOW_36_48,          CH_SET_UNII_MID_52_64,
+     CH_SET_UNII_WW_100_140,    CH_SET_UNII_UPPER_149_161},
+    /* idx=7: Russia */
+    {CH_SET_2G4_1_13,           CH_SET_UNII_LOW_36_48,          CH_SET_UNII_MID_52_64,
+     CH_SET_UNII_WW_100_140,    CH_SET_UNII_UPPER_149_161},
+    /* idx=8: Indonesia */
+    {CH_SET_2G4_1_13,           CH_SET_UNII_LOW_NA,             CH_SET_UNII_MID_NA,
+     CH_SET_UNII_WW_NA,         CH_SET_UNII_UPPER_149_161},
+    /* idx=9: Canada */
+    {CH_SET_2G4_1_11,           CH_SET_UNII_LOW_36_48,          CH_SET_UNII_MID_52_64,
+     CH_SET_UNII_WW_100_116_132_140,    CH_SET_UNII_UPPER_149_165},
+    /* idx=10: Chile, India, Saudi Arabia, Singapore */
+    {CH_SET_2G4_1_13,           CH_SET_UNII_LOW_36_48,          CH_SET_UNII_MID_52_64,
+     CH_SET_UNII_WW_NA,         CH_SET_UNII_UPPER_149_165},
+    /* idx=11: Israel, Ukraine */
+    {CH_SET_2G4_1_13,           CH_SET_UNII_LOW_36_48,          CH_SET_UNII_MID_52_64,
+     CH_SET_UNII_WW_NA,         CH_SET_UNII_UPPER_NA},
+    /* idx=12: Jordan, Kuwait */
+    {CH_SET_2G4_1_13,           CH_SET_UNII_LOW_36_48,          CH_SET_UNII_MID_NA,
+     CH_SET_UNII_WW_NA,         CH_SET_UNII_UPPER_NA},
+    /* idx=13: South Korea */
+    {CH_SET_2G4_1_13,           CH_SET_UNII_LOW_36_48,          CH_SET_UNII_MID_52_64,
+     CH_SET_UNII_WW_100_128,    CH_SET_UNII_UPPER_149_165},
+    /* idx=14: Taiwan */
+    {CH_SET_2G4_1_11,           CH_SET_UNII_LOW_NA,             CH_SET_UNII_MID_52_64,
+     CH_SET_UNII_WW_100_140,    CH_SET_UNII_UPPER_149_165},
+    /* idx=15: EU all countries */
+    {CH_SET_2G4_1_13,           CH_SET_UNII_LOW_36_48,          CH_SET_UNII_MID_52_64,
+     CH_SET_UNII_WW_100_140,    CH_SET_UNII_UPPER_149_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          14  /* EU (Europe Union) */
+#define REG_DOMAIN_GROUP_NUM \
+        (sizeof(arSupportedRegDomains) / sizeof(DOMAIN_INFO_ENTRY))
+
+    UINT_16                 i, j;
+    P_DOMAIN_INFO_ENTRY     prDomainInfo;
+    P_REG_INFO_T            prRegInfo;
+    UINT_16                 u2TargetCountryCode;
+
+    ASSERT(prAdapter);
+
+    if (prAdapter->prDomainInfo) {
+        return prAdapter->prDomainInfo;
+    }
+
+    prRegInfo = &prAdapter->prGlueInfo->rRegInfo;
+
+    DBGLOG(RLM, INFO, ("Domain: map=%d, idx=%d, code=0x%04x\n",
+        prRegInfo->eRegChannelListMap, prRegInfo->ucRegChannelListIndex,
+        prAdapter->rWifiVar.rConnSettings.u2CountryCode));
+
+    if (prRegInfo->eRegChannelListMap == REG_CH_MAP_TBL_IDX &&
+        prRegInfo->ucRegChannelListIndex < REG_DOMAIN_GROUP_NUM) {
+        prDomainInfo = &arSupportedRegDomains[prRegInfo->ucRegChannelListIndex];
+        goto L_set_domain_info;
+    }
+    else if (prRegInfo->eRegChannelListMap == REG_CH_MAP_CUSTOMIZED) {
+        prDomainInfo = &prRegInfo->rDomainInfo;
+        goto L_set_domain_info;
+    }
+
+    u2TargetCountryCode = prAdapter->rWifiVar.rConnSettings.u2CountryCode;
+
+    /* If no matched country code, the final one will be used
+     * The final one is for Europe union now.
+     */
+    for (i = 0; i < REG_DOMAIN_GROUP_NUM; i++) {
+        prDomainInfo = &arSupportedRegDomains[i];
+
+        ASSERT((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 */
+        }
+    }
+
+    DATA_STRUC_INSPECTING_ASSERT(REG_DOMAIN_DEF_IDX < REG_DOMAIN_GROUP_NUM);
+
+    if (i >= REG_DOMAIN_GROUP_NUM) {
+        prDomainInfo = &arSupportedRegDomains[REG_DOMAIN_DEF_IDX];
+    }
+
+L_set_domain_info:
+
+    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,
+    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);
+
+    /* If no matched country code, the final one will be used */
+    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 (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
+    )
+{
+    P_DOMAIN_INFO_ENTRY     prDomainInfo;
+    P_CMD_SET_DOMAIN_INFO_T prCmd;
+    WLAN_STATUS             rStatus;
+    UINT_8                  i;
+    P_DOMAIN_SUBBAND_INFO   prSubBand;
+
+    prDomainInfo = rlmDomainGetDomainInfo(prAdapter);
+    ASSERT(prDomainInfo);
+
+    prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_SET_DOMAIN_INFO_T));
+    ASSERT(prCmd);
+
+    /* To do: exception handle */
+    if (!prCmd) {
+        DBGLOG(RLM, ERROR, ("Domain: no buf to send cmd\n"));
+        return;
+    }
+    kalMemZero(prCmd, sizeof(CMD_SET_DOMAIN_INFO_T));
+
+    prCmd->u2CountryCode = prAdapter->rWifiVar.rConnSettings.u2CountryCode;
+    prCmd->u2Reserved = 0;
+    prCmd->uc2G4Bandwidth =
+            prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode;
+    prCmd->uc5GBandwidth =
+            prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode;
+
+    for (i = 0; i < 6; 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;
+        }
+    }
+
+    /* Update domain info to chip */
+    rStatus = 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 */
+                );
+
+    ASSERT(rStatus == WLAN_STATUS_PENDING);
+
+    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;
+}
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/rlm_obss.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/rlm_obss.c
new file mode 100755 (executable)
index 0000000..143d721
--- /dev/null
@@ -0,0 +1,461 @@
+/*
+** $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,
+    UINT_32     u4Data
+    );
+
+/*******************************************************************************
+*                              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, (UINT_32) 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.
+     */
+    if ((prBssInfo->auc2G_20mReqChnlList[0] > 0 ||
+         prBssInfo->auc2G_NonHtChnlList[0] > 0) &&
+        (prMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter,
+                      MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN)) != 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)
+            ((UINT_32)(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,
+    UINT_32     u4Data
+    )
+{
+    P_BSS_INFO_T        prBssInfo;
+
+    prBssInfo = (P_BSS_INFO_T) u4Data;
+    ASSERT(prBssInfo);
+
+#if CFG_ENABLE_WIFI_DIRECT
+    /* AP mode */
+    if (prAdapter->fgIsP2PRegistered &&
+        (IS_NET_ACTIVE(prAdapter, prBssInfo->ucNetTypeIndex)) &&
+        (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT)) {
+
+        prBssInfo->fgObssActionForcedTo20M = FALSE;
+
+        /* Check if Beacon content need to be updated */
+        rlmUpdateParamsForAP(prAdapter, prBssInfo, FALSE);
+        
+        return;
+    }
+#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/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/rlm_protection.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/rlm_protection.c
new file mode 100755 (executable)
index 0000000..27ffda0
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+** $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/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/roaming_fsm.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/roaming_fsm.c
new file mode 100755 (executable)
index 0000000..c941873
--- /dev/null
@@ -0,0 +1,583 @@
+/*
+** $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 = %ld\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;
+
+    return;
+} /* 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 = %ld\n", kalGetTimeTick()));
+
+    prRoamingFsmInfo = (P_ROAMING_INFO_T)&(prAdapter->rWifiVar.rRoamingInfo);
+
+    prRoamingFsmInfo->eCurrentState = ROAMING_STATE_IDLE;
+
+    return;
+} /* 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 = %ld\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);
+
+    return;
+} /* 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 */
+    ROAMING_ENABLE_CHECK(prRoamingFsmInfo);
+
+    DBGLOG(ROAMING, LOUD, ("->roamingFsmScanResultsUpdate(): Current Time = %ld\n", kalGetTimeTick()));
+
+    GET_CURRENT_SYSTIME(&prRoamingFsmInfo->rRoamingDiscoveryUpdateTime);
+
+    return;
+} /* 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"));
+                         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 */
+    ROAMING_ENABLE_CHECK(prRoamingFsmInfo);
+
+    prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]);
+    if (prAisBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) {
+        return;
+    }
+
+    DBGLOG(ROAMING, EVENT, ("EVENT-ROAMING START: Current Time = %ld\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);
+    }
+
+    return;
+} /* 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 UINT_32 u4Param
+    )
+{
+    P_ROAMING_INFO_T prRoamingFsmInfo;
+    ENUM_ROAMING_STATE_T eNextState;
+
+    prRoamingFsmInfo = (P_ROAMING_INFO_T)&(prAdapter->rWifiVar.rRoamingInfo);
+
+    /* Check Roaming Conditions */
+    ROAMING_ENABLE_CHECK(prRoamingFsmInfo);
+
+    DBGLOG(ROAMING, EVENT, ("EVENT-ROAMING DISCOVERY: Current Time = %ld\n", kalGetTimeTick()));
+
+    /* DECISION -> DISCOVERY */
+    /* Errors as IDLE, DISCOVERY, ROAM -> DISCOVERY */
+    if (prRoamingFsmInfo->eCurrentState != ROAMING_STATE_DECISION) {
+        return;
+    }
+
+    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)(u4Param&0xff);
+        }
+
+        roamingFsmSteps(prAdapter, eNextState);
+    }
+
+    return;
+} /* 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 */
+    ROAMING_ENABLE_CHECK(prRoamingFsmInfo);
+
+    DBGLOG(ROAMING, EVENT, ("EVENT-ROAMING ROAM: Current Time = %ld\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);
+    }
+
+    return;
+} /* 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 */
+    ROAMING_ENABLE_CHECK(prRoamingFsmInfo);
+
+    DBGLOG(ROAMING, EVENT, ("EVENT-ROAMING FAIL: reason %x Current Time = %ld\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);
+    }
+
+    return;
+} /* 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);
+
+    ROAMING_ENABLE_CHECK(prRoamingFsmInfo);
+
+    DBGLOG(ROAMING, EVENT, ("EVENT-ROAMING ABORT: Current Time = %ld\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);
+    }
+
+    return;
+} /* 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 = %ld\n", kalGetTimeTick()));
+
+    if (ROAMING_EVENT_DISCOVERY == prParam->u2Event) {
+        roamingFsmRunEventDiscovery(prAdapter, prParam->u2Data);
+    }
+
+    return WLAN_STATUS_SUCCESS;
+}
+
+#endif
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/rsn.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/rsn.c
new file mode 100755 (executable)
index 0000000..a576b1d
--- /dev/null
@@ -0,0 +1,2671 @@
+/*
+** $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 indiate pmkid candidate while no new one scaned.
+ *
+ * 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;
+        }
+        else {
+            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\n"));
+        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\n"));
+        return 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,
+            prBssRsnInfo->u4PairwiseKeyCipherSuiteCount,
+            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%08lx/0x%08lx)\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%08lx/0x%08lx)\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) {
+            }
+            DBGLOG(RSN, TRACE, ("Failed to select pairwise/group cipher for BT over Wi-Fi network (0x%08lx/0x%08lx)\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%08lx/0x%08lx)\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)((UINT_32)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 avaiable 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;
+
+    DEBUGFUNC("rsnGenerateWPAIE");
+
+    ASSERT(prMsduInfo);
+
+    pucBuffer = (PUINT_8)((UINT_32)prMsduInfo->prPacket +
+                          (UINT_32)prMsduInfo->u2FrameLength);
+
+    ASSERT(pucBuffer);
+
+    eNetworkId = (ENUM_NETWORK_TYPE_INDEX_T)prMsduInfo->ucNetworkType;
+
+    //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
+    {
+        /* 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)((UINT_32)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 (eNetworkId == NETWORK_TYPE_AIS_INDEX &&
+            rsnSearchPmkidEntry(prAdapter, prStaRec->aucMacAddr, &u4Entry)) {
+            //DBGLOG(RSN, TRACE, ("Add Pmk at assoc req\n"));
+            //DBGLOG(RSN, TRACE, ("addr " MACSTR" PMKID "MACSTR"\n",
+            //    MAC2STR(prAdapter->rWifiVar.rAisSpecificBssInfo.arPmkidCache[u4Entry].rBssidInfo.arBSSID), MAC2STR(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 "MACSTR" ind=%d\n", MAC2STR(prStaRec->aucMacAddr), u4Entry));
+                DBGLOG(RSN, TRACE, ("use PMKID "MACSTR"\n", MAC2STR(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);
+
+    /* 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 ["MACSTR"]\n",
+    //    MAC2STR(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 " MACSTR " with pre-auth to candidate list\n",
+            MAC2STR(prAisSpecBssInfo->arPmkidCandicate[i].aucBssid)));
+    }
+    else {
+        prAisSpecBssInfo->arPmkidCandicate[i].u4PreAuthFlags = 0;
+        DBGLOG(RSN, TRACE, ("Add " MACSTR " without pre-auth to candidate list\n",
+            MAC2STR(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, (MACSTR" at PMKID cache!!\n", MAC2STR(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 "MACSTR" to PMKID cache!!\n", MAC2STR(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  UINT_32           u4Parm
+    )
+{
+    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);
+    }
+
+    return;
+} /* 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, (MACSTR" %d\n", MAC2STR(prPmkidEvent->arCandidateList[count].arBSSID),
+                prPmkidEvent->arCandidateList[count].u4Flags));
+            count++;
+        }
+    }
+
+    /* PMKID Candidate List */
+    prPmkidEvent->u4Version = 1;
+    prPmkidEvent->u4NumCandidates = count;
+    DBGLOG(RSN, TRACE, ("rsnGeneratePmkidIndication #%d\n", 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)((UINT_32)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 */
+        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)
+        ((UINT_32)(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, INFO, ("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, INFO, ("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 "
+           MACSTR"\n", MAC2STR(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 " MACSTR"\n", MAC2STR(prStaRec->aucMacAddr)));
+        return;
+    }
+    DBGLOG(RSN, TRACE, ("IEEE 802.11: Sending SA Query Response to "
+           MACSTR"\n", MAC2STR(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)
+        ((UINT_32)(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=%lu)\n", (unsigned long) 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 "
+           MACSTR"\n", MAC2STR(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
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/saa_fsm.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/saa_fsm.c
new file mode 100755 (executable)
index 0000000..65eee2b
--- /dev/null
@@ -0,0 +1,2022 @@
+/*
+** $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 $
+ *
+ * 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 reseting 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) {
+                        }
+                        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,
+                                (UINT_32)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,
+                                (UINT_32)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,
+                                (UINT_32)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
+    saaFsmSteps(prAdapter, prStaRec, SAA_STATE_SEND_AUTH1, (P_SW_RFB_T)NULL);
+
+    return;
+} /* 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) {
+        return WLAN_STATUS_INVALID_PACKET;
+    }
+
+    ASSERT(prStaRec);
+
+    DBGLOG(SAA, LOUD, ("EVENT-TX DONE: Current Time = %ld\n", kalGetTimeTick()));
+
+    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,
+                        (UINT_32)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,
+                        (UINT_32)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,
+                        (UINT_32)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 = %ld\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;
+    }
+
+    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 = %ld\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);
+    }
+
+    return;
+} /* 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) {
+        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 ["MACSTR"], Status Code = %d\n",
+                    MAC2STR(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 ["MACSTR"], Status Code = %d\n",
+                    MAC2STR(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 */
+    }
+
+    return;
+} /* 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 ["MACSTR"], Status Code = %d\n",
+                    MAC2STR(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;
+#if DBG
+    P_WLAN_DEAUTH_FRAME_T prDeauthFrame;
+#endif /* DBG */
+
+
+    ASSERT(prSwRfb);
+    prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx);
+
+#if DBG
+    prDeauthFrame = (P_WLAN_DEAUTH_FRAME_T) prSwRfb->pvHeader;
+
+    DBGLOG(SAA, INFO, ("Rx Deauth frame from BSSID=["MACSTR"].\n",
+        MAC2STR(prDeauthFrame->aucBSSID)));
+#endif /* DBG */
+
+    do {
+
+        /* We should have the corresponding Sta Record. */
+        if (!prStaRec) {
+            break;
+        }
+
+        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) {
+
+                /* Check if this is the AP we are associated or associating with */
+                if (authProcessRxDeauthFrame(prSwRfb,
+                            prStaRec->aucMacAddr,
+                            &prStaRec->u2ReasonCode) == WLAN_STATUS_SUCCESS) {
+
+                    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);
+
+                        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 */
+                    }
+
+                }
+
+            }
+
+        }
+#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;
+#if DBG
+    P_WLAN_DISASSOC_FRAME_T prDisassocFrame;
+#endif /* DBG */
+
+
+    ASSERT(prSwRfb);
+    prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx);
+
+#if DBG
+    prDisassocFrame = (P_WLAN_DISASSOC_FRAME_T) prSwRfb->pvHeader;
+
+    DBGLOG(SAA, INFO, ("Rx Disassoc frame from BSSID=["MACSTR"].\n",
+        MAC2STR(prDisassocFrame->aucBSSID)));
+#endif /* DBG */
+
+    do {
+
+        /* We should have the corresponding Sta Record. */
+        if (!prStaRec) {
+            break;
+        }
+
+        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) {
+
+                /* Check if this is the AP we are associated or associating with */
+                if (assocProcessRxDisassocFrame(prAdapter,
+                            prSwRfb,
+                            prStaRec->aucMacAddr,
+                            &prStaRec->u2ReasonCode) == WLAN_STATUS_SUCCESS) {
+
+                    if (STA_STATE_3 == prStaRec->ucStaState) {
+                        P_MSG_AIS_ABORT_T prAisAbortMsg;
+
+                        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 */
+                    }
+
+                }
+
+            }
+
+        }
+#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)) {
+            /* 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
+
+    return;
+} /* 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;
+
+    return;
+} /* 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);
+    return;
+} /* 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: ["MACSTR"]\n", MAC2STR(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 Infomation
+    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
+         * <AssocReq>     <AssocResp w/i ERP>     <BARKER(Long)>  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
+         * <AssocReq>     <AssocResp w/o ERP>     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);
+
+    return;
+} /* end of joinComplete() */
+#endif
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/scan.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/scan.c
new file mode 100755 (executable)
index 0000000..cd52555
--- /dev/null
@@ -0,0 +1,2955 @@
+/*
+** $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 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 continous memory demands
+ * 1) correct typo in scan.c
+ * 2) TX descriptors, RX descriptos and management buffer should use virtually continous 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 continous memory demands
+ * separate kalMemAlloc() into virtually-continous and physically-continous 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 occured
+ *
+ * 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 Microsoft 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 Microsoft 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(((UINT_32)pucBSSBuff - (UINT_32)&prScanInfo->aucScanBuffer[0]) == SCN_MAX_BUFFER_SIZE);
+
+    /* reset freest channel information */
+    prScanInfo->fgIsSparseChannelValid = FALSE;
+
+    return;
+} /* 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);
+
+    return;
+} /* 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;
+            }
+            else {
+                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;
+            }
+            else {
+                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() */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @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;
+
+    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;
+            }
+            else { // CASE III
+                P_LINK_T prBSSDescList;
+                P_LINK_T prFreeBSSDescList;
+
+
+                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: "MACSTR", Current Time = %08lx, Update Time = %08lx\n",
+                    //prBssDesc, MAC2STR(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: "MACSTR", Update Time = %08lx\n",
+                //prBssDescOldest, MAC2STR(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: "MACSTR", Update Time = %08lx\n",
+                //prBssDescOldest, MAC2STR(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 */
+        }
+    }
+
+    return;
+} /* 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);
+        }
+    }
+
+    return;
+} /* 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;
+
+    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:
+        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;
+    }
+
+    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/ASUS 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;
+        }
+    }
+
+
+    //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
+            //ASSERT(0); // still no space available ?
+            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);
+
+        prBssDesc->eBSSType = eBSSType;
+
+        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) {
+                return prBssDesc;
+            }
+            // for received beacons too close in time domain
+            else if(rCurrentTime - prBssDesc->rUpdateTime <= REPLICATED_BEACON_TIME_THRESHOLD) {
+                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;
+        }
+    }
+
+    /* NOTE: Keep consistency of Scan Record during JOIN process */
+    if ((fgIsNewBssDesc == FALSE) && prBssDesc->fgIsConnecting) {
+        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/ASUS 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);
+                }
+
+            }
+            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
+            {
+                UINT_8 ucOuiType;
+                UINT_16 u2SubTypeVersion;
+#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;
+    }
+
+    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)((UINT_32)(prSwRfb->pvHeader) + WLAN_MAC_MGMT_HEADER_LEN));
+
+    return WLAN_STATUS_SUCCESS;
+
+} /* end of scanAddScanResult() */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @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)) {
+#ifndef _lint
+        ASSERT(0);
+#endif /* _lint */
+        return rStatus;
+    }
+
+#if CFG_SLT_SUPPORT
+    prSltInfo = &prAdapter->rWifiVar.rSltInfo;
+
+    if (prSltInfo->fgIsDUT) {
+        DBGLOG(P2P, 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;
+
+    //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
+
+            // <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 &&
+                    rlmDomainIsLegalChannel(prAdapter, prBssDesc->eBand, prBssDesc->ucChannelNum) == TRUE) {
+                ENUM_BAND_T eBand;
+                UINT_8 ucChannel;
+                BOOLEAN fgAddToScanResult;
+
+                /* check ucChannelNum/eBand for adjacement channel filtering */
+                if(cnmAisInfraChannelFixed(prAdapter, &eBand, &ucChannel) == TRUE &&
+                        (eBand != prBssDesc->eBand || ucChannel != prBssDesc->ucChannelNum)) {
+                    fgAddToScanResult = FALSE;
+                }
+                else {
+                    fgAddToScanResult = TRUE;
+                }
+
+                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;
+    UINT_8 ucChannel;
+
+    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) {
+        fgIsFixedChannel = cnmAisInfraChannelFixed(prAdapter, &eBand, &ucChannel);
+    }
+    else {
+        fgIsFixedChannel = FALSE;
+    }
+
+#if DBG
+    if (prConnSettings->ucSSIDLen < ELEM_MAX_LEN_SSID) {
+        prConnSettings->aucSSID[prConnSettings->ucSSIDLen] = '\0';
+    }
+#endif
+
+    DBGLOG(SCN, INFO, ("SEARCH: Num Of BSS_DESC_T = %d, Look for SSID: %s\n",
+        prBSSDescList->u4NumElem, prConnSettings->aucSSID));
+
+
+    //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, INFO, ("SEARCH: ["MACSTR"], SSID:%s\n",
+                            MAC2STR(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, INFO, ("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)) ) {
+
+            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 which has Status Code = %d (Curr = %ld/Last Join = %ld)\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)) ||
+                ((prConnSettings->eOPMode == NET_TYPE_IBSS || prConnSettings->eOPMode == NET_TYPE_DEDICATED_IBSS) &&
+                 (prBssDesc->eBSSType != BSS_TYPE_IBSS))) {
+
+                DBGLOG(SCN, INFO, ("SEARCH: Ignore eBSSType = %s\n",
+                    ((prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE) ?
+                        "INFRASTRUCTURE" : "IBSS")));
+                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, INFO, ("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:["MACSTR"]\n\n",
+                              MAC2STR(prBssDesc->aucBSSID)));
+                    continue;
+                }
+
+                //4 <4.3.2> Check Peer's capability
+                if (ibssCheckCapabilityForAdHocMode(prAdapter, prBssDesc) == WLAN_STATUS_FAILURE) {
+
+                    DBGLOG(SCN, INFO,
+                        ("SEARCH: Ignore BSS DESC MAC: "MACSTR", Capability is not supported for current AdHoc Mode.\n",
+                        MAC2STR(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: ["MACSTR"], Smaller TSF\n", MAC2STR(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:["MACSTR"]\n\n",
+                          MAC2STR(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:["MACSTR"]\n\n",
+                          MAC2STR(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: "MACSTR", Capability is not supported for current AdHoc Mode.\n",
+                    MAC2STR(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: ["MACSTR"], Current BSSID: ["MACSTR"].\n",
+                            MAC2STR(prPrimaryBssDesc->aucBSSID), MAC2STR(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;
+            }
+            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) {
+                if (wapiPerformPolicySelection(prAdapter, prPrimaryBssDesc)) {
+                    fgIsFindFirst = TRUE;
+                }
+                else {
+                    /* Can't pass the Encryption Status Check, get next one */
+                    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 "MACSTR"\n",
+                                MAC2STR(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: "MACSTR" has nonzero Status Code = %d\n",
+                        MAC2STR(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 ["MACSTR"]: RCPI = %d, Primary ["MACSTR"]: RCPI = %d\n",
+                    MAC2STR(prCandidateBssDesc->aucBSSID), prCandidateBssDesc->ucRCPI,
+                    MAC2STR(prPrimaryBssDesc->aucBSSID), prPrimaryBssDesc->ucRCPI));
+
+                ASSERT(!(prCandidateBssDesc->fgIsConnected &&
+                         prPrimaryBssDesc->fgIsConnected));
+
+                /* 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) {
+
+                        prCandidateBssDesc = prPrimaryBssDesc;
+                        prCandidateStaRec = prPrimaryStaRec;
+                        continue;
+                    }
+                }
+                else if (prPrimaryBssDesc->fgIsConnected) {
+                    if (prCandidateBssDesc->ucRCPI < prPrimaryBssDesc->ucRCPI + ROAMING_NO_SWING_RCPI_STEP) {
+
+                        prCandidateBssDesc = prPrimaryBssDesc;
+                        prCandidateStaRec = prPrimaryStaRec;
+                        continue;
+                    }
+                }
+                else if (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) {
+
+                /* TODO(Kevin): Check which one has minimum channel load in its channel */
+            }
+#endif
+        }
+    }
+
+    return prCandidateBssDesc;
+
+} /* end of scanSearchBssDescByPolicy() */
+
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/scan_fsm.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/scan_fsm.c
new file mode 100755 (executable)
index 0000000..2fc9b8b
--- /dev/null
@@ -0,0 +1,1109 @@
+/*
+** $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 */
+
+/*******************************************************************************
+*                                 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);
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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;
+    UINT_32 i;
+
+    ASSERT(prAdapter);
+
+    prScanInfo = &(prAdapter->rWifiVar.rScanInfo);
+    prScanParam = &prScanInfo->rScanParam;
+
+    // send command packet for scan
+    kalMemZero(&rCmdScanReq, sizeof(CMD_SCAN_REQ));
+
+    rCmdScanReq.ucSeqNum        = prScanParam->ucSeqNum;
+    rCmdScanReq.ucNetworkType   = (UINT_8)prScanParam->eNetTypeIndex;
+    rCmdScanReq.ucScanType      = (UINT_8)prScanParam->eScanType;
+    rCmdScanReq.ucSSIDType      = prScanParam->ucSSIDType;
+
+    if(prScanParam->ucSSIDNum == 1) {
+        COPY_SSID(rCmdScanReq.aucSSID,
+                rCmdScanReq.ucSSIDLength,
+                prScanParam->aucSpecifiedSSID[0],
+                prScanParam->ucSpecifiedSSIDLen[0]);
+    }
+
+    rCmdScanReq.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)
+         */
+        rCmdScanReq.ucChannelListNum    = prScanParam->ucChannelListNum;
+
+        for(i = 0 ; i < rCmdScanReq.ucChannelListNum ; i++) {
+            rCmdScanReq.arChannelList[i].ucBand =
+                (UINT_8) prScanParam->arChnlInfoList[i].eBand;
+
+            rCmdScanReq.arChannelList[i].ucChannelNum =
+                (UINT_8)prScanParam->arChnlInfoList[i].ucChannelNum;
+        }
+    }
+
+#if CFG_ENABLE_WIFI_DIRECT
+    if(prScanParam->eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) {
+        rCmdScanReq.u2ChannelDwellTime = prScanParam->u2PassiveListenInterval;
+    }
+#endif
+
+    if(prScanParam->u2IELen <= MAX_IE_LENGTH) {
+        rCmdScanReq.u2IELen = prScanParam->u2IELen;
+    }
+    else {
+        rCmdScanReq.u2IELen = MAX_IE_LENGTH;
+    }
+
+    if (prScanParam->u2IELen) {
+        kalMemCopy(rCmdScanReq.aucIE,
+                prScanParam->aucIE,
+                sizeof(UINT_8) * rCmdScanReq.u2IELen);
+    }
+
+    wlanSendSetQueryCmd(prAdapter,
+            CMD_ID_SCAN_REQ,
+            TRUE,
+            FALSE,
+            FALSE,
+            NULL,
+            NULL,
+            OFFSET_OF(CMD_SCAN_REQ, aucIE) + rCmdScanReq.u2IELen,
+            (PUINT_8)&rCmdScanReq,
+            NULL,
+            0);
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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;
+    UINT_32 i;
+
+    ASSERT(prAdapter);
+
+    prScanInfo = &(prAdapter->rWifiVar.rScanInfo);
+    prScanParam = &prScanInfo->rScanParam;
+
+    // send command packet for scan
+    kalMemZero(&rCmdScanReq, sizeof(CMD_SCAN_REQ_V2));
+
+    rCmdScanReq.ucSeqNum        = prScanParam->ucSeqNum;
+    rCmdScanReq.ucNetworkType   = (UINT_8)prScanParam->eNetTypeIndex;
+    rCmdScanReq.ucScanType      = (UINT_8)prScanParam->eScanType;
+    rCmdScanReq.ucSSIDType      = prScanParam->ucSSIDType;
+
+    for (i = 0 ; i < prScanParam->ucSSIDNum; i++) {
+        COPY_SSID(rCmdScanReq.arSSID[i].aucSsid,
+                rCmdScanReq.arSSID[i].u4SsidLen,
+                prScanParam->aucSpecifiedSSID[i],
+                prScanParam->ucSpecifiedSSIDLen[i]);
+    }
+
+    rCmdScanReq.u2ProbeDelayTime    = (UINT_8)prScanParam->u2ProbeDelayTime;
+    rCmdScanReq.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)
+         */
+        rCmdScanReq.ucChannelListNum    = prScanParam->ucChannelListNum;
+
+        for(i = 0 ; i < rCmdScanReq.ucChannelListNum ; i++) {
+            rCmdScanReq.arChannelList[i].ucBand =
+                (UINT_8) prScanParam->arChnlInfoList[i].eBand;
+
+            rCmdScanReq.arChannelList[i].ucChannelNum =
+                (UINT_8)prScanParam->arChnlInfoList[i].ucChannelNum;
+        }
+    }
+
+#if CFG_ENABLE_WIFI_DIRECT
+    if(prScanParam->eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) {
+        rCmdScanReq.u2ChannelDwellTime = prScanParam->u2PassiveListenInterval;
+    }
+#endif
+
+    if(prScanParam->u2IELen <= MAX_IE_LENGTH) {
+        rCmdScanReq.u2IELen = prScanParam->u2IELen;
+    }
+    else {
+        rCmdScanReq.u2IELen = MAX_IE_LENGTH;
+    }
+
+    if (prScanParam->u2IELen) {
+        kalMemCopy(rCmdScanReq.aucIE,
+                prScanParam->aucIE,
+                sizeof(UINT_8) * rCmdScanReq.u2IELen);
+    }
+
+    wlanSendSetQueryCmd(prAdapter,
+            CMD_ID_SCAN_REQ_V2,
+            TRUE,
+            FALSE,
+            FALSE,
+            NULL,
+            NULL,
+            OFFSET_OF(CMD_SCAN_REQ_V2, aucIE) + rCmdScanReq.u2IELen,
+            (PUINT_8)&rCmdScanReq,
+            NULL,
+            0);
+
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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);
+    }
+
+    return;
+}
+
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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);
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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;
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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;
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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;
+        }
+    }
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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, LOUD, ("Unexpected SCAN-DONE event: SeqNum = %d, Current State = %d\n",
+                 prScanDone->ucSeqNum,
+                 prScanInfo->eCurrentState));
+    }
+
+    return;
+} /* 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;
+
+    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:
+            DBGLOG(SCN, LOUD, ("Unexpected Network Type: %d\n", ucNetTypeIndex));
+            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;
+    }
+}
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/sec_fsm.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/sec_fsm.c
new file mode 100755 (executable)
index 0000000..862b9fa
--- /dev/null
@@ -0,0 +1,1255 @@
+/*
+** $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 Microsoft 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,
+                       (UINT_32)prSta);
+
+        cnmTimerInitTimer(prAdapter,
+                       &prAdapter->rWifiVar.rAisSpecificBssInfo.rRsnaBlockTrafficTimer,
+                       (PFN_MGMT_TIMEOUT_FUNC)secFsmEventEndOfCounterMeasure,
+                       (UINT_32)prSta);
+
+    }
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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
+*/
+/*----------------------------------------------------------------------------*/
+__KAL_INLINE__ VOID
+secFsmTrans_INIT_to_CHECK_OK (
+    IN P_ADAPTER_T          prAdapter,
+    IN P_STA_RECORD_T       prSta
+    )
+{
+    secSetPortBlocked(prAdapter, prSta, FALSE);
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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
+*/
+/*----------------------------------------------------------------------------*/
+__KAL_INLINE__ VOID
+secFsmTrans_INIT_to_INITIATOR_PORT_BLOCKED (
+    IN P_ADAPTER_T          prAdapter,
+    IN P_STA_RECORD_T       prSta
+    )
+{
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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
+*/
+/*----------------------------------------------------------------------------*/
+__KAL_INLINE__ VOID
+secFsmTrans_INIT_to_RESPONDER_PORT_BLOCKED (
+    IN P_ADAPTER_T          prAdapter,
+    IN P_STA_RECORD_T       prSta
+    )
+{
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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
+*/
+/*----------------------------------------------------------------------------*/
+__KAL_INLINE__ VOID
+secFsmTrans_INITIATOR_PORT_BLOCKED_to_CHECK_OK (
+    IN P_ADAPTER_T          prAdapter,
+    IN P_STA_RECORD_T       prSta
+    )
+{
+    secSetPortBlocked(prAdapter, prSta, FALSE);
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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
+*/
+/*----------------------------------------------------------------------------*/
+__KAL_INLINE__ VOID
+secFsmTrans_RESPONDER_PORT_BLOCKED_to_CHECK_OK (
+    IN P_ADAPTER_T          prAdapter,
+    IN P_STA_RECORD_T       prSta
+    )
+{
+    secSetPortBlocked(prAdapter, prSta, FALSE);
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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 -
+*/
+/*----------------------------------------------------------------------------*/
+__KAL_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));
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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
+*/
+/*----------------------------------------------------------------------------*/
+__KAL_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 -
+*/
+/*----------------------------------------------------------------------------*/
+__KAL_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));
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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 -
+*/
+/*----------------------------------------------------------------------------*/
+__KAL_INLINE__ VOID
+secFsmTrans_COUNTERMEASURE_to_INIT (
+    IN P_ADAPTER_T          prAdapter,
+    IN P_STA_RECORD_T       prSta
+    )
+{
+
+    //Clear the counter measure flag
+    return;
+}
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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"MACSTR" TRANSITION: [%s] -> [%s]\n\n",
+                            MAC2STR(prSta->aucMacAddr),
+                            apucDebugSecState[prSecInfo->eCurrentState],
+                            apucDebugSecState[eNextState]));
+#else
+        DBGLOG(RSN, STATE, ("\n"MACSTR" [%d] TRANSITION: [%d] -> [%d]\n\n",
+                            MAC2STR(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 "MACSTR" network %d\n",
+        MAC2STR(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);
+    }
+
+    return;
+} /* 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 "MACSTR" network %d\n",
+        MAC2STR(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, (MACSTR" Sec state %s\n", MAC2STR(prSta->aucMacAddr),
+        apucDebugSecState[prSecInfo->eCurrentState]));
+#else
+    DBGLOG(RSN, TRACE, (MACSTR" Sec state [%d]\n", MAC2STR(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, (MACSTR " Sec state %s\n", MAC2STR(prSta->aucMacAddr),
+        apucDebugSecState[prSecInfo->eCurrentState]));
+#else
+    DBGLOG(RSN, TRACE, (MACSTR " Sec state [%d]\n", MAC2STR(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, (MACSTR " Sec state %s\n", MAC2STR(prSta->aucMacAddr),
+        apucDebugSecState[prSecInfo->eCurrentState]));
+#else
+    DBGLOG(RSN, TRACE, (MACSTR " Sec state [%d]\n", MAC2STR(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, (MACSTR " Sec state %s\n", MAC2STR(prSta->aucMacAddr),
+        apucDebugSecState[prSecInfo->eCurrentState]));
+#else
+    DBGLOG(RSN, TRACE, (MACSTR " Sec state [%d]\n", MAC2STR(prSta->aucMacAddr), prSecInfo->eCurrentState));
+#endif
+
+    prAdapter->rWifiVar.rAisSpecificBssInfo.u4RsnaLastMICFailTime = 0;
+
+    switch(prSecInfo->eCurrentState) {
+    case SEC_STATE_CHECK_OK:
+        {
+            prAdapter->rWifiVar.rAisSpecificBssInfo.fgCounterMeasure = TRUE;
+
+            //<Todo> 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, (MACSTR " Sec state %s\n", MAC2STR(prStaRec->aucMacAddr),
+        apucDebugSecState[prSecInfo->eCurrentState]));
+#else
+    DBGLOG(RSN, TRACE, (MACSTR " Sec state [%d]\n", MAC2STR(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, (MACSTR " Sec state %s\n", MAC2STR(prStaRec->aucMacAddr),
+        apucDebugSecState[prSecInfo->eCurrentState]));
+#else
+    DBGLOG(RSN, TRACE, (MACSTR " Sec state [%d]\n", MAC2STR(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;
+    }
+
+    return;
+}/* 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 UINT_32                u4Parm
+    )
+{
+    P_STA_RECORD_T            prStaRec;
+
+    DEBUGFUNC("secFsmRunEventEapolTxTimeout");
+
+    prStaRec = (P_STA_RECORD_T)u4Parm;
+
+    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,
+    UINT_32                 u4Parm
+    )
+{
+    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)u4Parm;
+
+    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, (MACSTR " Sec state %s\n", MAC2STR(prSta->aucMacAddr),
+        apucDebugSecState[prSecInfo->eCurrentState]));
+#else
+    DBGLOG(RSN, TRACE, (MACSTR " Sec state [%d]\n", MAC2STR(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);
+    }
+
+    return;
+}/* end of secFsmRunEventEndOfCounterMeasure */
+#endif
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/swcr.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/swcr.c
new file mode 100755 (executable)
index 0000000..0a65bb0
--- /dev/null
@@ -0,0 +1,1268 @@
+/*
+** $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
+extern SWCR_MAP_ENTRY_T g_arRlmArSwCrMap[];
+SWCR_MOD_MAP_ENTRY_T g_arSwCrAllMaps[] = {
+    { SWCR_MAP_NUM(g_arRlmArSwCrMap), g_arRlmArSwCrMap},  /* 0x00nn */
+    {0,NULL}
+};
+#endif
+
+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,
+    UINT_32 u4Param);
+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);
+
+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 = 0;
+static ENUM_SWCR_DBG_TYPE_T g_ucSwcrDebugCheckType = 0;
+static UINT_32 g_u4SwcrDebugFrameDumpType = 0;
+
+/*******************************************************************************
+*                           P R I V A T E   D A T A
+********************************************************************************
+*/
+#define TEST_PS 1
+
+const static 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: " MACSTR " Rcpi %u" "\n", MAC2STR(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 " MACSTR"\n",MAC2STR(prBssInfo->aucOwnMacAddr)));
+    DBGLOG(SW4, INFO, ("BSSID " MACSTR"\n",MAC2STR(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|
+                                            PARAM_PACKET_FILTER_MULTICAST);
+                        }
+                        else {
+                            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;
+                        }
+
+                    }
+            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) {
+    }
+    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 */
+    if ( (prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen)) == 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)((UINT_32)(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)(  (PUINT_8)((UINT_32)(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));
+
+    return;
+}
+
+
+
+
+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);
+    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, INFO, ("%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,
+                      (UINT_32) 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,
+    UINT_32 u4Param)
+{
+         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);
+
+    return;
+}
+
+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/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/wapi.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/wapi.c
new file mode 100755 (executable)
index 0000000..4d23378
--- /dev/null
@@ -0,0 +1,522 @@
+/*
+** $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 Microsoft 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)((UINT_32)prMsduInfo->prPacket +
+                          (UINT_32)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;
+        }
+        else {
+            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%08lx/0x%08lx)\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/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/wnm.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/mgmt/wnm.c
new file mode 100755 (executable)
index 0000000..c6871df
--- /dev/null
@@ -0,0 +1,349 @@
+/*
+** $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 = 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
+********************************************************************************
+*/
+
+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
+    );
+/*******************************************************************************
+*                              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 = %ld\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)
+        ((UINT_32)(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 "
+           MACSTR"\n", MAC2STR(prStaRec->aucMacAddr)));
+
+    // 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 "
+           MACSTR"\n", MAC2STR(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/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/cmd_buf.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/cmd_buf.c
new file mode 100755 (executable)
index 0000000..62653ab
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+** $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
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                                 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);
+    }
+
+} /* end of cmdBufInitialize() */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @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;
+        }
+        else {
+            prCmdInfo->u2InfoBufLen = 0;
+            prCmdInfo->fgIsOid = FALSE;
+            prCmdInfo->fgDriverDomainMCR = FALSE;
+        }
+    }
+
+    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/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/nic.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/nic.c
new file mode 100755 (executable)
index 0000000..ff64c68
--- /dev/null
@@ -0,0 +1,4425 @@
+/*
+** $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 similiar 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 continous memory demands
+ * 1) correct typo in scan.c
+ * 2) TX descriptors, RX descriptos and management buffer should use virtually continous 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 continous memory demands
+ * separate kalMemAlloc() into virtually-continous and physically-continous 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 occured
+ *
+ * 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(INIT, INFO, ("Allocating %ld bytes for %s.\n", u4Size, pucComment)); \
+            if ((pucMem = (PUINT_8)kalMemAlloc(u4Size, eMemType)) == (PUINT_8)NULL) { \
+                DBGLOG(INIT, ERROR, ("Could not allocate %ld bytes for %s.\n", u4Size, pucComment)); \
+                break; \
+            } \
+            ASSERT(((UINT_32)pucMem % 4) == 0); \
+            DBGLOG(INIT, INFO, ("Virtual Address = %08lx for %s.\n", (UINT_32)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
+********************************************************************************
+*/
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @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. */
+        /* <TODO> 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(INIT, ERROR, ("Could not allocate %ld 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(INIT, ERROR, ("Could not allocate %ld 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
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @brief disable global interrupt
+*
+* @param prAdapter pointer to the Adapter handler
+*
+* @return (none)
+*/
+/*----------------------------------------------------------------------------*/
+VOID
+nicDisableInterrupt (
+    IN P_ADAPTER_T prAdapter
+    )
+{
+    ASSERT(prAdapter);
+
+    HAL_BYTE_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_BYTE_WR(prAdapter, MCR_WHLPCR, WHLPCR_INT_EN_SET);
+    }
+
+    return;
+} /* 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( (UINT_32)&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 = 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;
+
+    return;
+} /* 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(INIT, 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++) {
+
+#if CFG_SDIO_INTR_ENHANCE
+        nicSDIOReadIntStatus(prAdapter, &u4IntStatus);
+#else
+        HAL_MCR_RD(prAdapter, MCR_WHISR, &u4IntStatus);
+#endif /* CFG_SDIO_INTR_ENHANCE */
+
+        //DBGLOG(INIT, 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",
+                (u4IntStatus & ~WHIER_DEFAULT), u4IntStatus, 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#: %ld, event:%d, func: 0x%x\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
+*/
+/*----------------------------------------------------------------------------*/
+BOOL
+nicVerifyChipID (
+    IN P_ADAPTER_T prAdapter
+    )
+{
+    UINT_32 u4CIR = 0;
+
+    ASSERT(prAdapter);
+
+    HAL_MCR_RD(prAdapter, MCR_WCIR, &u4CIR );
+
+    DBGLOG(INIT, TRACE,("Chip ID: 0x%x\n", u4CIR & WCIR_CHIP_ID));
+    DBGLOG(INIT, TRACE,("Revision ID: 0x%x\n", ((u4CIR & WCIR_REVISION_ID) >> 16)));
+
+    if ((u4CIR & WCIR_CHIP_ID) != MTK_CHIP_REV) {
+        return FALSE;
+    }
+
+    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;
+
+    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
+    )
+{
+
+    return;
+} /* end of nicProcessFwOwnBackInterrupt() */
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @brief .
+*
+* @param prAdapter  Pointer to the Adapter structure.
+*
+* @return (none)
+*/
+/*----------------------------------------------------------------------------*/
+VOID
+nicProcessSoftwareInterrupt(
+    IN P_ADAPTER_T prAdapter
+    )
+{
+    UINT_32 u4IntrBits;
+
+    ASSERT(prAdapter);
+
+    u4IntrBits = prAdapter->u4IntStatus & BITS(8, 31);
+
+    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));
+
+    return;
+} /* end of nicProcessSoftwareInterrupt() */
+
+VOID
+nicPutMailbox (
+    IN P_ADAPTER_T prAdapter,
+    IN UINT_32 u4MailboxNum,
+    IN UINT_32 u4Data
+    )
+{
+    if (u4MailboxNum == 0) {
+        HAL_MCR_WR(prAdapter, MCR_H2DSM0R, u4Data);
+    } else if (u4MailboxNum == 1) {
+        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(prAdapter, MCR_D2HRM0R, pu4Data);
+    } else if (u4MailboxNum == 1) {
+        HAL_MCR_RD(prAdapter, MCR_D2HRM1R, pu4Data);
+    } else {
+        ASSERT(0);
+    }
+}
+
+VOID
+nicSetSwIntr (
+    IN P_ADAPTER_T prAdapter,
+    IN UINT_32 u4SwIntrBitmap
+    )
+{
+    /* NOTE:
+     *  SW interrup 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(INIT, 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;
+        else {
+            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;
+        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);
+
+    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();
+
+    KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST);
+    do {
+        if (prAdapter == NULL) {
+
+            ASSERT(FALSE);
+            break;
+        }
+
+        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) {
+
+                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;
+    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;
+#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);
+    }
+
+    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(INIT, 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,
+            TRUE,
+            (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() */
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @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(INIT, LOUD, ("\n"));
+
+       printk("nicUpdateBeaconIETemplate\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(INIT, ERROR, ("Allocate CMD_INFO_T ==> FAILED.\n"));
+               printk("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;
+    }
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @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): %d \n", sizeof(AC_QUE_PARMS_T)));
+    DBGLOG(QM, EVENT, ("sizeof(CMD_UPDATE_WMM_PARMS): %d \n", sizeof(CMD_UPDATE_WMM_PARMS_T)));
+    DBGLOG(QM, EVENT, ("sizeof(WIFI_CMD_T): %d \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);
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @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);
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @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 */
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @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);
+
+    return;
+}
+
+
+#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;
+    }
+    else {
+        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;
+    }
+    else {
+        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)((UINT_32)(prAdapter->rWlanInfo.apucScanResultIEs[u4Idx]) + u4FreeSize);
+
+    u4ReserveSize = ((UINT_32)pucPivot) - (UINT_32)(&(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)((UINT_32)(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;
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @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(INIT, INFO, ("ArParam %u %u %u %u\n", u4ArSysParam0, u4ArSysParam1, u4ArSysParam2, u4ArSysParam3));
+    DBGLOG(INIT, INFO, ("ArVer %u AbwVer %u AgiVer %u\n", ucArVer, ucAbwVer, ucAgiVer));
+    DBGLOG(INIT, INFO, ("HtMask %x LegacyMask %x\n", u2HtClrMask, u2LegacyClrMask));
+    DBGLOG(INIT, 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(MT5931)
+    u4ChipId = 5931;
+#elif defined(MT6628)
+    u4ChipId = 6628;
+#endif
+
+    kalPrint("\n[MT%ld][wifi][Firmware] Assert at \"%s\" #%ld\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;
+
+    }
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @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;
+
+    }
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @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;
+
+    }
+
+    return;
+}
+
+#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/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/nic_cmd_event.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/nic_cmd_event.c
new file mode 100755 (executable)
index 0000000..c974394
--- /dev/null
@@ -0,0 +1,1651 @@
+/*
+** $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 microsoft 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_STRUC_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_STRUC_T);
+
+        prMcrRdInfo = (P_PARAM_CUSTOM_MCR_RW_STRUC_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_STRUC_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_STRUC_T);
+
+        prSwCtrlInfo = (P_PARAM_CUSTOM_SW_CTRL_STRUC_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 Infomation Length */
+        kalOidComplete(prAdapter->prGlueInfo,
+                       prCmdInfo->fgSetQuery,
+                       prCmdInfo->u4InformationBufferLength,
+                       WLAN_STATUS_SUCCESS);
+    }
+
+    return;
+}
+
+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 Infomation Length */
+        kalOidComplete(prAdapter->prGlueInfo,
+                       prCmdInfo->fgSetQuery,
+                       0,
+                       WLAN_STATUS_SUCCESS);
+    }
+
+    kalIndicateStatusAndComplete(prAdapter->prGlueInfo,
+                    WLAN_STATUS_MEDIA_DISCONNECT,
+                    NULL,
+                    0);
+
+#if !defined(LINUX)
+    prAdapter->fgIsRadioOff = TRUE;
+#endif
+
+    return;
+}
+
+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 Infomation 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);
+    }
+
+    return;
+}
+
+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 Infomation Length */
+        kalOidComplete(prGlueInfo,
+                       prCmdInfo->fgSetQuery,
+                       u4QueryInfoLen,
+                       WLAN_STATUS_SUCCESS);
+    }
+
+    return;
+}
+
+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
+
+    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);
+
+        if(prLinkQuality->u2LinkSpeed == 0) {
+            *pu4LinkSpeed = 10000; /* 10K * 100bps = 1Mbps */
+        }
+        else {
+            *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
+    )
+{
+    UINT_32 u4WHISR = 0, u4Value = 0;
+    UINT_8 aucTxCount[8];
+
+    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) {
+            if (prCmdInfo->fgIsOid) {
+                /* Update Set Infomation Length */
+                kalOidComplete(prAdapter->prGlueInfo,
+                        prCmdInfo->fgSetQuery,
+                        prCmdInfo->u4SetInfoLen,
+                        WLAN_STATUS_NOT_SUPPORTED);
+
+            }
+            return;
+        }
+        else
+            kalMsleep(10);
+    }
+
+    // 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 Infomation 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
+
+    return;
+}
+
+VOID
+nicCmdEventLeaveRfTest(
+    IN P_ADAPTER_T  prAdapter,
+    IN P_CMD_INFO_T prCmdInfo,
+    IN PUINT_8      pucEventBuf
+    )
+{
+    UINT_32 u4WHISR = 0, u4Value = 0;
+    UINT_8 aucTxCount[8];
+
+    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) {
+            if (prCmdInfo->fgIsOid) {
+                /* Update Set Infomation Length */
+                kalOidComplete(prAdapter->prGlueInfo,
+                        prCmdInfo->fgSetQuery,
+                        prCmdInfo->u4SetInfoLen,
+                        WLAN_STATUS_NOT_SUPPORTED);
+
+            }
+            return;
+        }
+        else {
+            kalMsleep(10);
+        }
+    }
+
+    // 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 Infomation 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);
+
+    return;
+}
+
+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);
+
+    return;
+}
+
+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_STRUC_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_STRUC_T);
+
+        prEepromRdInfo = (P_PARAM_CUSTOM_EEPROM_RW_STRUC_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 Infomation 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. indiate 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_STRUC_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_STRUC_T);
+
+        prMemDumpInfo = (P_PARAM_CUSTOM_MEM_DUMP_STRUC_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;
+            printk("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++) {
+                printk("%02X ", prEventDumpMem->aucBuffer[i]);
+                if(i % 32 == 31) {
+                    printk("\n");
+                }
+            }
+#endif
+        }while(FALSE);
+#endif
+
+        if(prEventDumpMem->ucFragNum == 1) {
+        /* Store memory dump into sdcard,
+                * path /sdcard/dump_<current  system tick>_<memory address>_<memory length>.hex
+                */
+            u4CurTimeTick = kalGetTimeTick();
+            sprintf(aucPath, "/sdcard/dump_%ld_0x%08lX_%ld.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;
+
+}
+
+
+
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/nic_pwr_mgt.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/nic_pwr_mgt.c
new file mode 100755 (executable)
index 0000000..f469057
--- /dev/null
@@ -0,0 +1,802 @@
+/*
+** $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
+********************************************************************************
+*/extern BOOLEAN fgIsResetting;
+
+/*******************************************************************************
+*                           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;
+
+    ASSERT(prAdapter);
+
+    if(prAdapter->fgIsFwOwn == TRUE) {
+        return;
+    }
+    else {
+        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)
+*/
+/*----------------------------------------------------------------------------*/
+BOOLEAN
+nicpmSetDriverOwn (
+    IN P_ADAPTER_T prAdapter
+    )
+{
+#define LP_OWN_BACK_TOTAL_DELAY_MS      8192    //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, u4RegValue = 0;
+
+    ASSERT(prAdapter);
+
+    if(prAdapter->fgIsFwOwn == FALSE)
+        return fgStatus;
+
+    u4CurrTick = kalGetTimeTick();
+    i = 0;
+    while(1) {
+        HAL_MCR_RD(prAdapter, MCR_WHLPCR, &u4RegValue);
+
+        if (u4RegValue & WHLPCR_FW_OWN_REQ_SET) {
+            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;
+            break;
+        }
+        else {
+            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++;
+        }
+    }
+
+    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;
+
+#if defined(MT6620) || defined(MT6628)
+        /* 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 */
+        if ( (u4Status = nicInitializeAdapter(prAdapter)) != WLAN_STATUS_SUCCESS ) {
+            DBGLOG(INIT, ERROR, ("nicInitializeAdapter failed!\n"));
+            u4Status = WLAN_STATUS_FAILURE;
+            break;
+        }
+#endif
+
+    #if CFG_ENABLE_FW_DOWNLOAD
+        prFwMappingHandle = kalFirmwareImageMapping(prAdapter->prGlueInfo, &pvFwImageMapFile, &u4FwImgLength);
+        if(!prFwMappingHandle) {
+            DBGLOG(INIT, ERROR,("Fail to load FW image from file!\n"));
+            pvFwImageMapFile = NULL;
+        }
+
+        #if defined(MT6620) || defined(MT6628)
+        if (pvFwImageMapFile) {
+            /* 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(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!\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(INIT, 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(INIT, 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);
+        }
+        else {
+            u4Status = WLAN_STATUS_FAILURE;
+            break;
+        }
+
+        /* 4. send Wi-Fi Start command */
+            #if CFG_OVERRIDE_FW_START_ADDRESS
+        wlanConfigWifiFunc(prAdapter,
+                TRUE,
+                kalGetFwStartAddress(prAdapter->prGlueInfo));
+            #else
+        wlanConfigWifiFunc(prAdapter,
+                FALSE,
+                0);
+            #endif
+
+        #elif defined(MT5931)
+        if (pvFwImageMapFile) {
+            DBGLOG(INIT, TRACE, ("Download Address: 0x%08X\n", kalGetFwLoadAddress(prAdapter->prGlueInfo)));
+            DBGLOG(INIT, TRACE, ("Firmware Length:  0x%08X\n", u4FwImgLength));
+
+            do {
+                /* 1.0 whole-chip reset except HIFSYS */
+                HAL_MCR_WR(prAdapter, MCR_WMCSR, WMCSR_CHIP_RST);
+                HAL_MCR_WR(prAdapter, MCR_WMCSR, 0);
+
+                /* 1.1 wait for INIT_RDY */
+                i = 0;
+                while(1) {
+                    HAL_MCR_RD(prAdapter, MCR_WMCSR, &u4Value);
+
+                    if (u4Value & WMCSR_INI_RDY) {
+                        DBGLOG(INIT, TRACE, ("INIT-RDY detected\n"));
+                        break;
+                    }
+                    else if(kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE
+                            || fgIsBusAccessFailed == TRUE) {
+                        u4Status = WLAN_STATUS_FAILURE;
+                        break;
+                    }
+                    else if(i >= CFG_RESPONSE_POLLING_TIMEOUT) {
+                        DBGLOG(INIT, ERROR, ("Waiting for Init Ready bit: Timeout\n"));
+                        u4Status = WLAN_STATUS_FAILURE;
+                        break;
+                    }
+                    else {
+                        i++;
+                        kalMsleep(10);
+                    }
+                }
+
+                /* 1.2 set KSEL/FLEN */
+                HAL_MCR_WR(prAdapter, MCR_FWCFG, u4FwImgLength >> 6);
+
+                /* 1.3 enable FWDL_EN */
+                HAL_MCR_WR(prAdapter, MCR_WMCSR, WMCSR_FWDLEN);
+
+                /* 1.4 wait for PLL_RDY */
+                i = 0;
+                while(1) {
+                    HAL_MCR_RD(prAdapter, MCR_WMCSR, &u4Value);
+
+                    if (u4Value & WMCSR_PLLRDY) {
+                        DBGLOG(INIT, TRACE, ("PLL-RDY detected\n"));
+                        break;
+                    }
+                    else if(kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE
+                            || fgIsBusAccessFailed == TRUE) {
+                        u4Status = WLAN_STATUS_FAILURE;
+                        break;
+                    }
+                    else if(i >= CFG_RESPONSE_POLLING_TIMEOUT) {
+                        DBGLOG(INIT, ERROR, ("Waiting for PLL Ready bit: Timeout\n"));
+                        u4Status = WLAN_STATUS_FAILURE;
+                        break;
+                    }
+                    else {
+                        i++;
+                        kalMsleep(10);
+                    }
+                }
+
+                /* 2.1 turn on HIFSYS firmware download mode */
+                HAL_MCR_WR(prAdapter, MCR_FWDLSR, FWDLSR_FWDL_MODE);
+
+                /* 2.2 set starting address */
+                u4FwLoadAddr = kalGetFwLoadAddress(prAdapter->prGlueInfo);
+                HAL_MCR_WR(prAdapter, MCR_FWDLDSAR, u4FwLoadAddr);
+
+                /* 3. upload firmware */
+                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(INIT, ERROR, ("Firmware scatter download failed!\n"));
+                        u4Status = WLAN_STATUS_FAILURE;
+                        break;
+                    }
+                }
+
+                /* 4.1 poll FWDL_OK & FWDL_FAIL bits */
+                i = 0;
+                while(1) {
+                    HAL_MCR_RD(prAdapter, MCR_WMCSR, &u4Value);
+
+                    if (u4Value & WMCSR_DL_OK) {
+                        DBGLOG(INIT, TRACE, ("DL_OK detected\n"));
+                        break;
+                    }
+                    else if(kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE
+                            || fgIsBusAccessFailed == TRUE
+                            || (u4Value & WMCSR_DL_FAIL)) {
+                        DBGLOG(INIT, ERROR, ("DL_FAIL detected: 0x%08X\n", u4Value));
+                        u4Status = WLAN_STATUS_FAILURE;
+                        break;
+                    }
+                    else if(i >= CFG_RESPONSE_POLLING_TIMEOUT) {
+                        DBGLOG(INIT, ERROR, ("Waiting for DL_OK/DL_FAIL bit: Timeout\n"));
+                        u4Status = WLAN_STATUS_FAILURE;
+                        break;
+                    }
+                    else {
+                        i++;
+                        kalMsleep(10);
+                    }
+                }
+
+                /* 4.2 turn off HIFSYS download mode */
+                HAL_MCR_WR(prAdapter, MCR_FWDLSR, 0);
+
+            } while (FALSE);
+        }
+        else {
+            DBGLOG(INIT, ERROR, ("No Firmware found!\n"));
+            u4Status = WLAN_STATUS_FAILURE;
+            break;
+        }
+
+        #endif
+    #endif
+
+        /* 5. check Wi-Fi FW asserts ready bit */
+        DBGLOG(INIT, TRACE, ("wlanAdapterStart(): Waiting for Ready bit..\n"));
+        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;
+                break;
+            }
+            else if(i >= CFG_RESPONSE_POLLING_TIMEOUT) {
+                DBGLOG(INIT, ERROR, ("Waiting for Ready bit: Timeout\n"));
+                u4Status = WLAN_STATUS_FAILURE;
+                break;
+            }
+            else {
+                i++;
+                kalMsleep(10);
+            }
+        }
+
+#if defined(MT5931)
+        // Acquire LP-OWN
+        ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter);
+    #if !CFG_ENABLE_FULL_PM
+        nicpmSetDriverOwn(prAdapter);
+    #endif
+
+        /* 2. Initialize the Adapter */
+        if ( (u4Status = nicInitializeAdapter(prAdapter)) != WLAN_STATUS_SUCCESS ) {
+            DBGLOG(INIT, ERROR, ("nicInitializeAdapter failed!\n"));
+            u4Status = WLAN_STATUS_FAILURE;
+            break;
+        }
+#endif
+
+        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/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/nic_rx.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/nic_rx.c
new file mode 100755 (executable)
index 0000000..596d8de
--- /dev/null
@@ -0,0 +1,3528 @@
+/*
+** $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 availble RX counter and QUE_MGT used count
+ * correct comment.
+ *
+ * 07 27 2011 cp.wu
+ * [WCXRP00000876] [MT5931][Drver] Decide to retain according to currently availble 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 LENTH 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 <limits.h>
+#else
+#include <linux/limits.h>
+#endif
+
+/*******************************************************************************
+*                              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
+    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((UINT_32)(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;
+    #if !defined(MT5931)
+    HAL_CFG_MAX_HIF_RX_LEN_NUM(prAdapter, CFG_SDIO_MAX_RX_AGG_NUM);
+    #endif
+#else
+    #if !defined(MT5931)
+    HAL_CFG_MAX_HIF_RX_LEN_NUM(prAdapter, 1);
+    #endif
+#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
+
+    return;
+} /* end of nicRxInitialize() */
+
+
+#if defined(MT5931)
+/*----------------------------------------------------------------------------*/
+/*!
+* @brief Initialize HIF RX control registers explicitly
+*
+* @param prAdapter      Pointer to the Adapter structure.
+*
+* @return (none)
+*/
+/*----------------------------------------------------------------------------*/
+VOID
+nicRxPostInitialize (
+    IN P_ADAPTER_T prAdapter
+    )
+{
+    P_RX_CTRL_T prRxCtrl;
+    DEBUGFUNC("nicRxPostInitialize");
+
+    ASSERT(prAdapter);
+    prRxCtrl = &prAdapter->rRxCtrl;
+
+#if CFG_SDIO_RX_AGG
+    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
+
+} /* end of nicRxPostInitialize() */
+#endif
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @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);
+
+    return;
+} /* 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;
+    BOOL 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 availble 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;
+    }
+    else {
+        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
+        }
+        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);
+    }
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @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);
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @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;
+
+    DEBUGFUNC("nicRxProcessDataPacket");
+    //DBGLOG(INIT, TRACE, ("\n"));
+
+    ASSERT(prAdapter);
+    ASSERT(prSwRfb);
+
+    prHifRxHdr = prSwRfb->prHifRxHdr;
+    prRxCtrl = &prAdapter->rRxCtrl;
+
+    nicRxFillRFB(prAdapter, prSwRfb);
+
+#if 1 /* Check 1x Pkt */
+    if (prSwRfb->u2PacketLen > 14) {
+        PUINT_8 pc = (PUINT_8)prSwRfb->pvHeader;
+        UINT_16 u2Etype = 0;
+
+        u2Etype = (pc[ETH_TYPE_LEN_OFFSET] << 8) | (pc[ETH_TYPE_LEN_OFFSET + 1]);
+
+#if CFG_SUPPORT_WAPI
+        if (u2Etype == ETH_P_1X || u2Etype == ETH_WPI_1X) {
+            DBGLOG(RSN, INFO, ("R1X len=%d\n", prSwRfb->u2PacketLen));
+        }
+#else
+        if (u2Etype == ETH_P_1X) {
+            DBGLOG(RSN, INFO, ("R1X len=%d\n", prSwRfb->u2PacketLen));
+        }
+#endif
+        else if (u2Etype == ETH_P_PRE_1X) {
+            DBGLOG(RSN, INFO, ("Pre R1X len=%d\n", prSwRfb->u2PacketLen));
+        }
+    }
+#endif
+
+#if CFG_TCP_IP_CHKSUM_OFFLOAD || CFG_TCP_IP_CHKSUM_OFFLOAD_NDIS_60
+    {
+        UINT_32 u4TcpUdpIpCksStatus;
+
+        u4TcpUdpIpCksStatus = *((PUINT_32)((UINT_32)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
+
+        if((prRetSwRfb = qmHandleRxPackets(prAdapter, prSwRfb)) != NULL) {
+            do {
+                // save next first
+                prNextSwRfb = (P_SW_RFB_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prRetSwRfb);
+
+                switch(prRetSwRfb->eDst) {
+                case RX_PKT_DESTINATION_HOST:
+                    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)
+*
+*/
+/*----------------------------------------------------------------------------*/
+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");
+    //DBGLOG(INIT, TRACE, ("\n"));
+
+    ASSERT(prAdapter);
+    ASSERT(prSwRfb);
+
+    prEvent = (P_WIFI_EVENT_T) prSwRfb->pucRecvBuff;
+    prGlueInfo = prAdapter->prGlueInfo;
+
+    // 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);
+
+                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;
+
+                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, INFO, ("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:["MACSTR"]\n",
+                prActivateStaRec->ucStaRecIdx,
+                MAC2STR(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:["MACSTR"]\n",
+                prDeactivateStaRec->ucStaRecIdx);
+
+            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:
+        {
+            P_EVENT_TX_DONE_T prTxDone;
+            prTxDone = (P_EVENT_TX_DONE_T)(prEvent->aucBuffer);
+
+            DBGLOG(INIT, TRACE,("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(INIT, 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:
+        DBGLOG(INIT, INFO,("EVENT_ID_BSS_BEACON_TIMEOUT\n"));
+
+        if (prAdapter->fgDisBcnLostDetection == FALSE) {
+            P_EVENT_BSS_BEACON_TIMEOUT_T prEventBssBeaconTimeout;
+            prEventBssBeaconTimeout = (P_EVENT_BSS_BEACON_TIMEOUT_T)(prEvent->aucBuffer);
+
+            if(prEventBssBeaconTimeout->ucNetTypeIndex == NETWORK_TYPE_AIS_INDEX) {
+                aisBssBeaconTimeout(prAdapter);
+            }
+#if CFG_ENABLE_WIFI_DIRECT
+            else if((prAdapter->fgIsP2PRegistered) &&
+                (prEventBssBeaconTimeout->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX)) {
+
+                p2pFsmRunEventBeaconTimeout(prAdapter);
+            }
+#endif
+#if CFG_ENABLE_BT_OVER_WIFI
+            else if(prEventBssBeaconTimeout->ucNetTypeIndex == NETWORK_TYPE_BOW_INDEX) {
+            }
+#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(INIT, INFO,("EVENT_ID_STA_AGING_TIMEOUT %u " MACSTR "\n",
+                                prEventStaAgingTimeout->ucStaRecIdx, MAC2STR(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:
+#if DBG
+        {
+            P_WLAN_MAC_HEADER_T prWlanMacHeader;
+
+            prWlanMacHeader = (P_WLAN_MAC_HEADER_T)&prEvent->aucBuffer[0];
+            DBGLOG(RX, INFO, ("nicRx: aucAddr1: "MACSTR"\n", MAC2STR(prWlanMacHeader->aucAddr1)));
+            DBGLOG(RX, INFO, ("nicRx: aucAddr2: "MACSTR"\n", MAC2STR(prWlanMacHeader->aucAddr2)));
+        }
+#endif
+         /* 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(RX, INFO, ("Send Deauth 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
+            printk(KERN_INFO DRV_NAME "BCM BWCS Event: %02x%02x%02x%02x\n", prEventBwcsStatus->u.aucBTPParams[0],
+                prEventBwcsStatus->u.aucBTPParams[1],
+                prEventBwcsStatus->u.aucBTPParams[2],
+                prEventBwcsStatus->u.aucBTPParams[3]);
+
+            printk(KERN_INFO DRV_NAME "BCM BWCS Event: aucBTPParams[0] = %02x, aucBTPParams[1] = %02x, aucBTPParams[2] = %02x, aucBTPParams[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
+            printk(KERN_INFO DRV_NAME "BCM FW status: %02x%02x%02x%02x\n", prEventBwcsStatus->u.aucBTPParams[0],
+                prEventBwcsStatus->u.aucBTPParams[1],
+                prEventBwcsStatus->u.aucBTPParams[2],
+                prEventBwcsStatus->u.aucBTPParams[3]);
+
+            printk(KERN_INFO DRV_NAME "BCM FW status: aucBTPParams[0] = %02x, aucBTPParams[1] = %02x, aucBTPParams[2] = %02x, aucBTPParams[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_ACCESS_REG:
+    case EVENT_ID_NIC_CAPABILITY:
+    case EVENT_ID_BASIC_CONFIG:
+    case EVENT_ID_MAC_MCAST_ADDR:
+    case EVENT_ID_ACCESS_EEPROM:
+    case EVENT_ID_TEST_STATUS:
+    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
+    BOOL   fgMfgDrop = FALSE;
+#endif
+    ASSERT(prAdapter);
+    ASSERT(prSwRfb);
+
+    nicRxFillRFB(prAdapter, prSwRfb);
+
+    ucSubtype = (*(PUINT_8)(prSwRfb->pvHeader) & MASK_FC_SUBTYPE )>> OFFSET_OF_FC_SUBTYPE;
+
+#if 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(SW4, INFO, ("QM RX MGT: net %u sta idx %u wlan idx %u ssn %u ptype %u subtype %u 11 %u\n",
+                    HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr),
+                    prHifRxHdr->ucStaRecIdx,
+                    prSwRfb->ucWlanIdx,
+                    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) {
+#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;
+        }
+        else
+#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);
+}
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @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){
+            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:
+                    DBGLOG(RX, ERROR, ("ucPacketType = %d\n", prSwRfb->ucPacketType));
+                    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));
+                    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;
+    BOOL 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)((UINT_32)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 (RX_STATUS_TEST_MORE_FLAG(u4HwAppendDW));
+    while (FALSE);
+
+    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;
+    BOOL 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 = %d\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 (%d)\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(prAdapter, &u2RxLength, &u2Tmp);
+            }
+            else if(rxNum == 1) {
+                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;
+
+    return;
+}/* 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;
+    BOOL 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);
+            //DBGLOG(RX, TRACE, ("RxPktNum %d in rxPort %d\n", u2RxPktNum, rxNum));
+            // 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));
+
+                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);
+
+    return;
+}
+#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(&prRxCtrl->rFreeSwRfbList, prQueEntry);
+    }
+    else {
+        QUEUE_INSERT_TAIL(&prRxCtrl->rIndicatedRfbList, prQueEntry);
+    }
+
+    KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE);
+    return;
+} /* 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
+    )
+{
+    ASSERT(prAdapter);
+
+#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) {
+        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);
+    }
+
+    return;
+} /* 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 :%9ld", prRxCtrl->rFreeSwRfbList.u4NumElem));
+    SPRINTF(pucCurrBuf, ("\nFREE RFB w/o BUF LIST :%9ld", prRxCtrl->rIndicatedRfbList.u4NumElem));
+    SPRINTF(pucCurrBuf, ("\nRECEIVED RFB LIST     :%9ld", prRxCtrl->rReceivedRfbList.u4NumElem));
+
+    SPRINTF(pucCurrBuf, ("\n\n"));
+
+    //*pu4Count = (UINT_32)((UINT_32)pucCurrBuf - (UINT_32)pucBuffer);
+
+    return;
+} /* 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);
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @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 : %ld\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);
+
+    return;
+}
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @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, i = 0;
+    WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS;
+    BOOL fgResult = TRUE;
+    UINT_32 u4Time, u4Current;
+
+    DEBUGFUNC("nicRxWaitResponse");
+
+    ASSERT(prAdapter);
+    ASSERT(pucRspBuffer);
+    ASSERT(ucPortIdx < 2);
+
+    u4Time = (UINT_32)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 = (UINT_32)kalGetTimeTick();
+
+            if((u4Current > u4Time) && ((u4Current - u4Time) > RX_RESPONSE_TIMEOUT)) {
+                return WLAN_STATUS_FAILURE;
+            }
+            else if(u4Current < u4Time && ((u4Current + (0xFFFFFFFF - u4Time)) > RX_RESPONSE_TIMEOUT)) {
+                return WLAN_STATUS_FAILURE;
+            }
+
+            /* Response packet is not ready */
+            kalUdelay(50);
+
+            i++;
+        }
+        else if (u4PktLen > u4MaxRespBufferLen) {
+            DBGLOG(RX, WARN, ("Not enough Event Buffer: required length = 0x%x, available buffer length = %d\n",
+                u4PktLen, u4MaxRespBufferLen));
+
+            return WLAN_STATUS_FAILURE;
+        }
+        else {
+            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);
+
+    return;
+} /* 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);
+
+    return;
+} /* 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);
+
+    if((prSwRfb = qmFlushRxQueues(prAdapter)) != 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;
+
+    switch (prActFrame->ucCategory) {
+    case CATEGORY_PUBLIC_ACTION:
+
+    #if CFG_ENABLE_WIFI_DIRECT
+        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
+    default:
+        break;
+    } /* end of switch case */
+
+    return WLAN_STATUS_SUCCESS;
+}
+
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/nic_tx.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/nic_tx.c
new file mode 100755 (executable)
index 0000000..641f585
--- /dev/null
@@ -0,0 +1,1977 @@
+/*
+** $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 availble 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 refering 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);
+
+    return;
+} /* 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.
+*/
+/*----------------------------------------------------------------------------*/
+WLAN_STATUS
+nicTxAcquireResource (
+    IN P_ADAPTER_T  prAdapter,
+    IN UINT_8       ucTC
+    )
+{
+    P_TX_CTRL_T prTxCtrl;
+    WLAN_STATUS u4Status = WLAN_STATUS_RESOURCES;
+    KAL_SPIN_LOCK_DECLARATION();
+
+    ASSERT(prAdapter);
+    prTxCtrl = &prAdapter->rTxCtrl;
+
+
+    KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
+
+//    DbgPrint("nicTxAcquireResource prTxCtrl->rTc.aucFreeBufferCount[%d]=%d\n", ucTC, prTxCtrl->rTc.aucFreeBufferCount[ucTC]);
+
+    if (prTxCtrl->rTc.aucFreeBufferCount[ucTC]) {
+
+        prTxCtrl->rTc.aucFreeBufferCount[ucTC]--;
+
+        DBGLOG(TX, EVENT, ("Acquire: TC = %d aucFreeBufferCount = %d\n",
+            ucTC, prTxCtrl->rTc.aucFreeBufferCount[ucTC]));
+
+        u4Status = WLAN_STATUS_SUCCESS;
+    }
+    KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
+
+    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;
+            }
+            else {
+                kalMsleep(NIC_TX_RESOURCE_POLLING_DELAY_MSEC);
+            }
+        }
+        else {
+            kalMsleep(NIC_TX_RESOURCE_POLLING_DELAY_MSEC);
+        }
+    }
+
+#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 UINT_8*      aucTxRlsCnt
+    )
+{
+    PUINT_32 pu4Tmp = (PUINT_32)aucTxRlsCnt;
+    P_TX_CTRL_T prTxCtrl;
+    BOOLEAN bStatus = FALSE;
+    UINT_32 i;
+
+    KAL_SPIN_LOCK_DECLARATION();
+
+
+    ASSERT(prAdapter);
+    prTxCtrl = &prAdapter->rTxCtrl;
+    // DBGLOG(TX, TRACE, ("\n"));
+    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];
+
+            if ((i==1) || (i==5)){
+                DBGLOG(TX, EVENT, ("Release: i = %d aucFreeBufferCount = %d\n",
+                    i, prTxCtrl->rTc.aucFreeBufferCount[i]));
+            }
+        }
+        KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
+#if 0
+        for (i = 0; i < TC_NUM; i++) {
+            DBGLOG(INIT, 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;
+
+    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: " MACSTR "\n",
+                MAC2STR(prMsduInfo->aucEthDestAddr));
+#endif
+
+        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);
+            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);
+
+            status = nicTxAcquireResource(prAdapter, prMsduInfo->ucTC);
+            ASSERT(status == WLAN_STATUS_SUCCESS)
+
+            break;
+
+        default:
+            ASSERT(0);
+            break;
+        }
+
+        prMsduInfo = prNextMsduInfo;
+    }
+
+    if(qDataPort0.u4NumElem > 0) {
+        nicTxMsduQueue(prAdapter, 0, &qDataPort0);
+    }
+
+    if(qDataPort1.u4NumElem > 0) {
+        nicTxMsduQueue(prAdapter, 1, &qDataPort1);
+    }
+
+    return WLAN_STATUS_SUCCESS;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @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) {
+
+            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);
+
+            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->fgIsBIP) {
+                rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BIP;
+            }
+
+            if(prMsduInfo->fgIsBasicRate) {
+                rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BASIC_RATE;
+            }
+
+#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(INIT, 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
+
+        // return
+        nicTxReturnMsduInfo(prAdapter, (P_MSDU_INFO_T)QUEUE_GET_HEAD(&rFreeQueue));
+    }
+
+    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;
+    }
+
+    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 = 0;
+
+        // <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(INIT, 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);
+    }
+
+    // <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);
+            ASSERT(prMsduInfo->pfTxDoneHandler != NULL);
+
+            // invoke done handler
+            prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, TX_RESULT_LIFE_TIMEOUT);
+
+            cnmMgtPktFree(prAdapter, prMsduInfo);
+        }
+        else {
+            break;
+        }
+    } while(TRUE);
+
+    return;
+} /* 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 */
+
+    ASSERT(prAdapter);
+
+    prTxCtrl = &prAdapter->rTxCtrl;
+    ASSERT(prTxCtrl);
+
+     /* 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);
+    }
+
+    return;
+} /* 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) {
+            if (prMsduInfo->pfTxDoneHandler) {
+                prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, TX_RESULT_DROPPED_IN_DRIVER);
+            }
+            cnmMemFree(prAdapter, prNativePacket);
+        }
+        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);
+    }
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @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;
+        }
+
+        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;
+    };
+
+    return;
+}
+
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @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;
+
+
+    ASSERT(prAdapter);
+
+    prGlueInfo = prAdapter->prGlueInfo;
+    ASSERT(prGlueInfo);
+
+    if (kalQoSFrameClassifierAndPacketInfo(prGlueInfo,
+                prPacket,
+                &ucPriorityParam,
+                &u4PacketLen,
+                aucEthDestAddr,
+                &fgIs1x,
+                &fgIsPAL,
+                &ucNetworkType) == FALSE) {
+        return FALSE;
+    }
+
+    /* 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);
+
+    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];
+
+        ASSERT(prTxCtrl->rTc.aucFreeBufferCount[u4Num] >= 0);
+        ASSERT(prTxCtrl->rTc.aucMaxNumOfBuffer[u4Num] >= 0);
+    }
+
+    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 maintainance 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 */
+        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/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/p2p_nic.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/p2p_nic.c
new file mode 100755 (executable)
index 0000000..592318b
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+** $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 (((UINT_32)prP2pInfo->pucCurrIePtr + (UINT_32)u2RxIELength) >
+                        (UINT_32)&prP2pInfo->aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN]) {
+                    /* Common Buffer is no enough. */
+                    u2RxIELength = (UINT_16)((UINT_32)&prP2pInfo->aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN] - (UINT_32)prP2pInfo->pucCurrIePtr);
+                }
+
+                /* Step to next buffer address. */
+                prP2pInfo->pucCurrIePtr = (PUINT_8)((UINT_32)prP2pInfo->pucCurrIePtr + (UINT_32)u2RxIELength);
+            }
+
+            /* Restore buffer pointer. */
+            prTargetResult->pucIeBuf = pucIeBuf;
+
+            if (pucRxIEBuf) {
+                /* If new received IE is availabe.
+                  * 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 " MACSTR", " MACSTR "\n", prP2pInfo->u4DeviceNum, MAC2STR(prP2pResult->aucDeviceAddr), MAC2STR(prTargetResult->aucDeviceAddr));
+
+            if (u2RxIELength) {
+                prTargetResult->pucIeBuf = prP2pInfo->pucCurrIePtr;
+
+                if (((UINT_32)prP2pInfo->pucCurrIePtr + (UINT_32)u2RxIELength) >
+                        (UINT_32)&prP2pInfo->aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN]) {
+                    /* Common Buffer is no enough. */
+                    u2IELength = (UINT_16)((UINT_32)&prP2pInfo->aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN] - (UINT_32)prP2pInfo->pucCurrIePtr);
+                }
+                else {
+                    u2IELength = u2RxIELength;
+                }
+
+                prP2pInfo->pucCurrIePtr = (PUINT_8)((UINT_32)prP2pInfo->pucCurrIePtr + (UINT_32)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/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/que_mgt.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/nic/que_mgt.c
new file mode 100755 (executable)
index 0000000..9555bed
--- /dev/null
@@ -0,0 +1,4802 @@
+/*
+** $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 $
+ *
+ * 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) Chnage 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
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+*                                 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
+********************************************************************************
+*/
+__KAL_INLINE__ VOID
+qmDetermineStaRecIndex(
+    IN P_ADAPTER_T   prAdapter,
+    IN P_MSDU_INFO_T prMsduInfo
+    );
+
+__KAL_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
+    );
+
+__KAL_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 Managment 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
+
+    //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;
+
+//    ASSERT(prQM->u4TimeToAdjust && prQM->u4TimeToUpdateQueLen);
+
+    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;
+
+    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;
+
+
+    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_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[%ld]\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"));
+        qmDeactivateStaRec(prAdapter, prStaRec->ucIndex); // To flush TX/RX queues and del RX BA agreements
+    }
+
+    //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, INFO, ("QM: +STA[%ld]\n", 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;
+
+    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(prNeedToFreeQue, (P_QUE_ENTRY_T)prMsduInfo);
+        }
+        else {
+            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;
+
+    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(%ld)\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;
+    P_QUE_T         prTxQue;
+    QUE_T           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){
+            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;
+
+        DBGLOG(QM, LOUD , ("***** ucStaRecIndex = %d *****\n",
+               prCurrentMsduInfo->ucStaRecIndex));
+
+
+        prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prCurrentMsduInfo->ucNetworkType]);
+
+        if(IS_NET_ACTIVE(prAdapter, prCurrentMsduInfo->ucNetworkType)) {
+
+            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);
+
+                    ASSERT(prStaRec);
+                    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){
+                        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;
+                            break;
+                        case 6:
+                        case 7:
+                            prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC3];
+                            ucTC = TC3_INDEX;
+                                    eAci = WMM_AC_VO_INDEX;
+                            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;
+                            }
+                    }
+                    else{
+                        prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC1];
+                        ucTC = TC1_INDEX;
+                    }
+                    }
+                    while(fgCheckACMAgain);
+
+                     //LOG_FUNC ("QoS %u UP %u TC %u",prStaRec->fgIsQoS,prCurrentMsduInfo->ucUserPriority, ucTC);
+
+                    break; /*default */
+             } /* switch (prCurrentMsduInfo->ucStaRecIndex) */
+
+             if(prCurrentMsduInfo->eSrc == TX_PACKET_FORWARDING) {
+                if(prTxQue->u4NumElem > 32) {
+                    DBGLOG(QM, INFO, ("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, INFO, ("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
+        QUEUE_INSERT_TAIL(prTxQue, (P_QUE_ENTRY_T)prCurrentMsduInfo);
+
+
+#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;
+    }
+
+
+    //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;
+
+    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){
+        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
+                    if(prBssInfo->fgIsNetAbsent && (ucTC!=TC4_INDEX)) {
+                        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 = %lu\n",
+        ucTC, *pu4HeadStaRecIndex));
+
+    //4 <2> Dequeue packets from the head STA
+
+    prCurrQueue = &prStaRec->arTxQueue[ucTC];
+    prDequeuedPkt = NULL;
+    fgChangeHeadSta = FALSE;
+
+    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){
+            break;
+        }
+        else{
+
+            QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T);
+#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: " MACSTR "\n",
+                    MAC2STR(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)) {
+                ASSERT(pucFreeQuota);
+                ASSERT(*pucFreeQuota>0);
+                if(*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 = %lu, u4HeadStaRecForwardCount = %lu\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){
+            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 = %lu\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;
+            }
+            else{
+
+                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: " MACSTR "\n",
+                        MAC2STR(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)) {
+                    prDequeuedPkt->ucPsForwardingType = PS_FORWARDING_MORE_DATA_ENABLED;
+                }
+
+                QUEUE_INSERT_TAIL(prQue,(P_QUE_ENTRY_T)prDequeuedPkt);
+                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 = %lu Left Resource = %lu\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;
+        }
+        else{
+            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);
+                    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: " MACSTR "\n",
+                            MAC2STR(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);
+        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
+       )
+{
+
+    INT_32 i;
+    P_MSDU_INFO_T prReturnedPacketListHead;
+    QUE_T rReturnedQue;
+
+    DBGLOG(QM, LOUD, ("Enter qmDequeueTxPackets\n"));
+
+    QUEUE_INITIALIZE(&rReturnedQue);
+
+    prReturnedPacketListHead = NULL;
+
+    /* 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[%u]\n", i));
+
+        qmDequeueTxPacketsFromPerStaQueues(
+            prAdapter,
+            &rReturnedQue,
+            (UINT_8)i,
+            prTcqStatus->aucFreeBufferCount[i],
+            prTcqStatus->aucMaxNumOfBuffer[i]
+            );
+
+        /* The aggregate number of dequeued packets */
+        DBGLOG(QM, LOUD, ("DQA)[%u](%lu)\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 initialize */
+    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]){
+                    ai4ExtraQuota[i] = prTcqStatus->aucFreeBufferCount[i];
+                    fgResourceRedistributed = FALSE;
+                }
+
+                i4TotalExtraQuota += ai4ExtraQuota[i];
+                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){
+                if ((-ai4ExtraQuota[i]) > i4TotalExtraQuota){
+                    ai4ExtraQuota[i] = (-i4TotalExtraQuota);
+                    fgResourceRedistributed = FALSE;
+                }
+
+                i4TotalExtraQuota += ai4ExtraQuota[i];
+                prTcqAdjust->acVariation[i] = (INT_8)(-ai4ExtraQuota[i]);
+            }
+        }
+
+        /* In case some TC is waiting for TX Done, continue to adjust TC quotas upon TX Done */
+        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 */
+    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);
+        }
+        else{
+            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
+    /* Check whether it is time to adjust the TC resource assignment */
+    if (--prQM->u4TimeToAdjustTcResource == 0){
+       /* The last assignment has not been completely applied */
+       if (prQM->fgTcResourcePostAnnealing){
+            /* Upon the next qmUpdateAverageTxQueLen function call, do this check again */
+            prQM->u4TimeToAdjustTcResource = 1;
+       }
+
+       /* The last assignment has been applied */
+       else{
+            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 [%ld %ld %ld %ld %ld %ld]\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
+    */
+
+    //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 = que_length + min_reserved_quota - current_quota */
+        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;
+        }
+
+        i4TotalResourceDemand += ai4PerTcResourceDemand[i];
+    }
+
+    //4 <2> Case 1: Demand <= Total Resource
+    if (i4TotalResourceDemand <= 0){
+        //4 <2.1> Satisfy every TC
+        for (i = 0; i < TC_NUM; i++){
+            /* Skip TC4 (not adjustable) */
+            if (i == TC4_INDEX) {
+                continue;
+            }
+
+            prQM->au4CurrentTcResource[i] += ai4PerTcResourceDemand[i];
+        }
+
+        //4 <2.2> Share the residual resource evenly
+        u4ShareCount= (TC_NUM - 1); /* excluding TC4 */
+        u4ResidualResource = (UINT_32)(-i4TotalResourceDemand);
+        u4Share = (u4ResidualResource/u4ShareCount);
+
+        for (i=0; i<TC_NUM; i++){
+            /* Skip TC4 (not adjustable) */
+            if (i == TC4_INDEX) {
+                continue;
+            }
+
+            prQM->au4CurrentTcResource[i] += u4Share;
+
+            /* Every TC is fully satisfied */
+            ai4PerTcResourceDemand[i] = 0;
+
+            /* The left resource will be allocated to TC3 */
+            u4ResidualResource -= u4Share;
+        }
+
+        //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 = QM_INITIAL_RESIDUAL_TC_RESOURCE;
+
+        //4 <3.1> Allocated resouce amount  = minimum of (guaranteed, total demand)
+        for (i=0; i<TC_NUM; i++){
+            /* Skip TC4 (not adjustable) */
+            if (i == TC4_INDEX) {
+                continue;
+            }
+
+            /* The demand can be fulfilled with the guaranteed resource amount */
+            if (prQM->au4CurrentTcResource[i] + ai4PerTcResourceDemand[i] < prQM->au4GuaranteedTcResource[i]){
+                prQM->au4CurrentTcResource[i] += ai4PerTcResourceDemand[i];
+                u4ResidualResource += (prQM->au4GuaranteedTcResource[i] - prQM->au4CurrentTcResource[i]);
+                ai4PerTcResourceDemand[i] = 0;
+            }
+
+            /* The demand can not be fulfilled with the guaranteed resource amount */
+            else{
+                ai4PerTcResourceDemand[i] -= (prQM->au4GuaranteedTcResource[i] - prQM->au4CurrentTcResource[i]);
+                prQM->au4CurrentTcResource[i] = prQM->au4GuaranteedTcResource[i];
+                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]){
+                        if (ai4PerTcResourceDemand[i] - u4Share){
+                            prQM->au4CurrentTcResource[i] += u4Share;
+                            u4ResidualResource -= u4Share;
+                            ai4PerTcResourceDemand[i] -= u4Share;
+                        }
+                        else{
+                            prQM->au4CurrentTcResource[i] += ai4PerTcResourceDemand[i];
+                            u4ResidualResource -= ai4PerTcResourceDemand[i];
+                            ai4PerTcResourceDemand[i] = 0;
+                        }
+                    }
+                }
+            }
+
+            /* By priority, allocate the left resource that is not divisible by u4Share */
+            if (u4ResidualResource == 0){
+                break;
+            }
+
+            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);
+    }
+
+    prQM->fgTcResourcePostAnnealing = TRUE;
+
+#if QM_PRINT_TC_RESOURCE_CTRL
+    /* Debug print */
+    DBGLOG(QM, LOUD, ("QM: TC Rsc %ld %ld %ld %ld %ld %ld\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 Managment 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;
+
+    //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",
+                    HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr),
+                    prHifRxHdr->ucStaRecIdx,
+                    prCurrSwRfb->ucWlanIdx,
+                    HIF_RX_HDR_GET_SN(prHifRxHdr),  /* The new SN of the frame */
+                    HIF_RX_HDR_GET_TID(prHifRxHdr),
+                    prCurrSwRfb->ucPacketType,
+                    HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr)));
+
+            DBGLOG_MEM8(SW4, TRACE, (PUINT_8)prCurrSwRfb->pvHeader, prCurrSwRfb->u2PacketLen);
+        }
+#endif
+        // DBGLOG(RX, TRACE, ("SN=%d, TID=%d\n", HIF_RX_HDR_GET_SN(prHifRxHdr), HIF_RX_HDR_GET_TID(prHifRxHdr)));
+        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( prAdapter->rRxCtrl.rFreeSwRfbList.u4NumElem
+                    > (CFG_RX_MAX_PKT_NUM - CFG_NUM_OF_QM_RX_PKT_NUM)  ) {
+
+                if(IS_BSS_ACTIVE(prBssInfo)) {
+                    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)) {
+                            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 */
+                }
+                else {
+                    DBGLOG(QM, TRACE, ("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;
+                }
+
+            }
+            else {
+                    /* Dont not occupy other SW RFB */
+                    DBGLOG(QM, TRACE, ("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;
+            }
+
+        }
+
+        /* 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)){
+#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);
+
+
+    /* 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;
+
+    DEBUGFUNC("qmProcessPktWithReordering");
+
+    ASSERT(prSwRfb);
+    ASSERT(prReturnedQue);
+    ASSERT(prSwRfb->prHifRxHdr);
+
+    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](%ld){%ld,%ld}\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
+
+
+        qmPopOutDueToFallWithin(prReorderQueParm, prReturnedQue);
+    }
+    /* 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);
+
+    }
+    /* 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
+
+        /* 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;
+
+    ASSERT(prSwRfb);
+    ASSERT(prReturnedQue);
+    ASSERT(prSwRfb->prHifRxHdr);
+
+    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](%ld){%d,%d}\n", prSwRfb->ucTid, u4SSN, prReorderQueParm->u2WinStart, prReorderQueParm->u2WinEnd));        
+        qmPopOutDueToFallAhead(prReorderQueParm, prReturnedQue);
+    }
+    else{
+        DBGLOG(QM, TRACE, ("QM:(BAR)(%d)(%ld){%ld,%ld}\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 ++;
+
+}
+
+
+VOID
+qmPopOutDueToFallWithin(
+    IN P_RX_BA_ENTRY_T prReorderQueParm,
+    OUT P_QUE_T prReturnedQue
+    )
+{
+    P_SW_RFB_T prReorderedSwRfb;
+    P_QUE_T prReorderQue;
+    BOOLEAN fgDequeuHead, fgMissing;
+    OS_SYSTIME rCurrentTime, *prMissTimeout;
+
+    prReorderQue = &(prReorderQueParm->rReOrderQue);
+
+    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;
+                       }
+            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);
+
+}
+
+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{
+        return (u4SnLess < u4SnGreater);
+    }
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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, INFO, ("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;
+}
+
+BOOL
+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;
+    }
+    else{
+       /* 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;
+
+    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 */
+    else{
+        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:
+                        {
+
+                            UINT_8 ucQosInfo;
+                            UINT_8 ucQosInfoAC;
+                            UINT_8 ucBmpAC;
+                        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 */
+    else{
+        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);
+        }
+
+        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;
+
+    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))){
+
+                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 */
+                    }
+                    else{
+                        P_AC_QUE_PARMS_T prAcQueParams;
+                        P_IE_WMM_PARAM_T prIeWmmParam;
+                        ENUM_WMM_ACI_T eAci;
+                        PUINT_8 pucWmmParamSetCount;
+                        //int i;
+
+                        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){
+                            if(*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, ("MQM: eAci = %d, ACM = %d, Aifsn = %d, CWmin = %d, CWmax = %d, TxopLimit = %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
+*/
+/*----------------------------------------------------------------------------*/
+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;
+
+    /* Goal: Determine whether the peer supports WMM/QoS and UAPSDU */
+    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 Param IE with a wrong length */
+                    }
+                    else{
+                        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 */
+                    }
+                    else{
+                        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;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @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;
+    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;
+
+    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);
+
+    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 intial 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);
+
+}
+
+
+#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
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @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;
+
+    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
+    };
+
+    P_BSS_INFO_T prBssInfo;
+    P_STA_RECORD_T prStaRec;
+    ENUM_WMM_ACI_T eAci;
+
+    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; }
+
+#if 0  // 20120220 frog: update beacon content & change OP mode is a separate event for P2P network.
+    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);
+
+    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 intial 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);
+
+}
+
+
+
+
+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_STRUC_INSPECTING_ASSERT(QM_MGMT_QUUEUD_THRESHOLD <= (NIC_TX_BUFF_COUNT_TC4));
+    DATA_STRUC_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)) {
+                return FRAME_ACTION_TX_PKT;
+            }
+
+        }
+
+        DBGLOG(QM, INFO, ("Drop packets Action (Inactive %u).\n",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) {
+             ASSERT(prMsduInfo!=NULL);
+             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) {
+                     break;
+                 }
+            }
+            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){
+                    if(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;
+            }
+             else {
+                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;
+            }
+            else {
+                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;
+    }
+    else {
+        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, TRACE, ("NAF=%d,%d,%d\n",
+        prEventBssStatus->ucNetTypeIdx, prBssInfo->fgIsNetAbsent, prBssInfo->ucBssFreeQuota));
+
+    if(!prBssInfo->fgIsNetAbsent) {
+          QM_DBG_CNT_INC(&(prAdapter->rQM),QM_DBG_CNT_27);
+    }
+    else {
+          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);
+
+        //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);
+
+            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
+    )
+{
+
+    UINT_8 ucFreeQuotaForNonDelivery;
+    UINT_8 ucFreeQuotaForDelivery;
+
+    ASSERT(prStaRec);
+    DBGLOG(QM, LOUD, ("qmUpdateFreeQuota orig ucFreeQuota=%d Mode %u New %u\n",
+        prStaRec->ucFreeQuota, ucUpdateMode, ucFreeQuota ));
+
+    if(!prStaRec->fgIsInPS)return;
+
+    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(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 {
+            /* !prStaRec->fgIsUapsdSupported */
+            ucFreeQuotaForNonDelivery = ucFreeQuota;
+            ucFreeQuotaForDelivery = 0;
+        }
+    } /* ucFreeQuota > 0 */
+
+    prStaRec->ucFreeQuotaForDelivery =  ucFreeQuotaForDelivery;
+    prStaRec->ucFreeQuotaForNonDelivery =  ucFreeQuotaForNonDelivery;
+
+    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;
+}
+
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_bow.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_bow.c
new file mode 100755 (executable)
index 0000000..bdd30aa
--- /dev/null
@@ -0,0 +1,1369 @@
+/*
+** $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 <linux/poll.h>
+#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;
+    }
+    else {
+#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;
+    }
+    else {
+        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->u4Flag & 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;
+
+    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->u4Flag & 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->u4Flag & 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->u4Flag & 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->u4Flag & 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: %d/%d\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));
+
+    return;
+}
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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];
+
+    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);
+        return NETDEV_TX_OK;
+     }
+
+    if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) {
+        DBGLOG(BOW, TRACE, ("GLUE_FLAG_HALT skip tx\n"));
+        dev_kfree_skb(prSkb);
+        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) {
+            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, ether_setup, CFG_MAX_TXQ_NUM);
+
+        if (!prGlueInfo->rBowInfo.prDevHandler) {
+            return FALSE;
+        }
+        else {
+            /* 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
+            memcpy(prGlueInfo->rBowInfo.prDevHandler->dev_addr, rMacAddr, ETH_ALEN);
+            memcpy(prGlueInfo->rBowInfo.prDevHandler->perm_addr, prGlueInfo->rBowInfo.prDevHandler->dev_addr, ETH_ALEN);
+
+            /* 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->func->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/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_cfg80211.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_cfg80211.c
new file mode 100755 (executable)
index 0000000..18c61c0
--- /dev/null
@@ -0,0 +1,1600 @@
+/*
+** $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 12 2012 wcpadmin
+** [ALPS00276400] Remove MTK copyright and legal header on GPL/LGPL related packages
+** .
+** 
+** 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..
+** 
+** 08 29 2012 chinglan.wang
+** [ALPS00349655] [Need Patch] [Volunteer Patch] [ALPS.JB] Daily build warning on [mt6575_phone_mhl-eng]
+** .
+ *
+**
+*/
+
+/*******************************************************************************
+*                         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"
+
+/*******************************************************************************
+*                              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_WAPI
+    extern UINT_8 keyStructBuf[1024];   /* add/remove key shared buffer */
+#else
+    extern UINT_8 keyStructBuf[100];   /* add/remove key shared buffer */
+#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 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:%lx\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, &params->key[16], 8);
+            kalMemCopy(tmp2, &params->key[24], 8);        
+            kalMemCopy(&rKey.aucKeyMaterial[16], tmp2, 8);
+            kalMemCopy(&rKey.aucKeyMaterial[24], tmp1, 8);
+        }
+    }
+
+    rKey.u4KeyLength = params->key_len;
+    rKey.u4Length =  ((UINT_32)&(((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);
+
+#if 1
+    printk("--> %s()\n", __func__);
+#endif
+
+    /* 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);
+    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:%lx\n", rStatus));
+    }
+    else {
+        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);
+
+#if 1
+    printk("--> %s()\n", __func__);
+#endif
+
+    /* not implemented */
+
+    return -EINVAL;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+ * @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,
+    u8 *mac,
+    struct station_info *sinfo
+    )
+{
+    P_GLUE_INFO_T prGlueInfo = NULL;
+    WLAN_STATUS rStatus;
+    PARAM_MAC_ADDRESS arBssid;
+    UINT_32 u4BufLen, u4Rate;
+    INT_32 i4Rssi;
+
+    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: ["MACSTR"] currently connected BSSID["MACSTR"]\n", 
+                    MAC2STR(mac), MAC2STR(arBssid)));
+        return -ENOENT;
+    }
+
+    /* 2. fill TX rate */
+    rStatus = kalIoctl(prGlueInfo,
+        wlanoidQueryLinkSpeed,
+        &u4Rate,
+        sizeof(u4Rate),
+        TRUE,
+        FALSE,
+        FALSE,
+        FALSE,
+        &u4BufLen);
+
+    if (rStatus != WLAN_STATUS_SUCCESS) {
+        DBGLOG(REQ, WARN, ("unable to retrieve link speed\n"));
+    }
+    else {
+        sinfo->filled |= STATION_INFO_TX_BITRATE;
+        sinfo->txrate.legacy = u4Rate / 1000; /* convert from 100bps to 100kbps */
+    }
+
+    if(prGlueInfo->eParamMediaStateIndicated != PARAM_MEDIA_STATE_CONNECTED) {
+        /* not connected */
+        DBGLOG(REQ, WARN, ("not yet connected\n"));
+    }
+    else {
+        /* 3. fill RSSI */
+        rStatus = kalIoctl(prGlueInfo,
+                wlanoidQueryRssi,
+                &i4Rssi,
+                sizeof(i4Rssi),
+                TRUE,
+                FALSE,
+                FALSE,
+                FALSE,
+                &u4BufLen);
+        
+        if (rStatus != WLAN_STATUS_SUCCESS) {
+            DBGLOG(REQ, WARN, ("unable to retrieve link speed\n"));
+        }
+        else {
+            sinfo->filled |= STATION_INFO_SIGNAL;
+           //in the cfg80211 layer, the signal is a signed char variable.
+            if(i4Rssi < -128)
+               sinfo->signal = -128;
+           else
+               sinfo->signal = i4Rssi; /* dBm */
+        }
+    }
+
+    sinfo->rx_packets = prGlueInfo->rNetDevStats.rx_packets;
+    sinfo->filled |= STATION_INFO_TX_PACKETS;
+    sinfo->tx_packets = prGlueInfo->rNetDevStats.tx_packets;
+    sinfo->filled |= STATION_INFO_TX_FAILED;
+
+#if 1
+   {
+            WLAN_STATUS rStatus;
+            UINT_32 u4XmitError = 0;
+//           UINT_32 u4XmitOk = 0;
+//          UINT_32 u4RecvError = 0;
+//           UINT_32 u4RecvOk = 0;
+//           UINT_32 u4BufLen;
+
+           /* @FIX ME: need a more clear way to do this */
+
+
+            rStatus = kalIoctl(prGlueInfo,
+                    wlanoidQueryXmitError,
+                    &u4XmitError,
+                    sizeof(UINT_32),
+                    TRUE,
+                    TRUE,
+                    TRUE,
+                    FALSE,
+                    &u4BufLen);
+
+           prGlueInfo->rNetDevStats.tx_errors = u4XmitError;
+
+   }
+#else
+         prGlueInfo->rNetDevStats.tx_errors = 0;
+#endif
+
+    sinfo->tx_failed = prGlueInfo->rNetDevStats.tx_errors;
+
+    return 0;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+ * @brief This routine is responsible for requesting to do a scan
+ *
+ * @param 
+ *
+ * @retval 0:       successful
+ *         others:  failure
+ */
+/*----------------------------------------------------------------------------*/
+int 
+mtk_cfg80211_scan (
+    struct wiphy *wiphy,
+    struct net_device *ndev,
+    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);
+    
+    kalMemZero(&rScanRequest, sizeof(PARAM_SCAN_REQUEST_EXT_T));
+    
+    /* check if there is any pending scan not yet finished */
+    if(prGlueInfo->prScanRequest != NULL) {
+        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 {
+        return -EINVAL;
+    }
+
+    if(request->ie_len > 0) {
+        rScanRequest.u4IELength = request->ie_len;
+        rScanRequest.pucIE = (PUINT_8)(request->ie);
+    }
+    else {
+        rScanRequest.u4IELength = 0;
+    }
+
+    rStatus = kalIoctl(prGlueInfo,
+        wlanoidSetBssidListScanExt,
+        &rScanRequest,
+        sizeof(PARAM_SCAN_REQUEST_EXT_T),
+        FALSE,
+        FALSE,
+        FALSE,
+        FALSE,
+        &u4BufLen);
+
+    if (rStatus != WLAN_STATUS_SUCCESS) {
+        DBGLOG(REQ, WARN, ("scan error:%lx\n", rStatus));
+        return -EINVAL;
+    }
+
+    prGlueInfo->prScanRequest = request;
+
+    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_SSID_T rNewSsid;
+    BOOLEAN fgCarryWPSIE = FALSE;
+    ENUM_PARAM_OP_MODE_T eOpMode;
+
+    prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy);
+    ASSERT(prGlueInfo);
+
+    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(INIT, INFO, ("wlanoidSetInfrastructureMode fail 0x%lx\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->prAdapter->rWifiVar.rConnSettings.fgWapiMode = FALSE;
+    //prGlueInfo->prAdapter->prGlueInfo->u2WapiAssocInfoIESz = 0;
+    prGlueInfo->fgWpsActive = FALSE;
+    //prGlueInfo->prAdapter->prGlueInfo->u2WSCAssocInfoIELen = 0;
+
+    if (sme->ie && sme->ie_len > 0) {
+        WLAN_STATUS rStatus;
+        UINT_32 u4BufLen;
+        PUINT_8 prDesiredIE = NULL;
+
+#if CFG_SUPPORT_WAPI
+        rStatus = kalIoctl(prGlueInfo,
+                wlanoidSetWapiAssocInfo,
+                sme->ie,
+                sme->ie_len,
+                FALSE,
+                FALSE,
+                FALSE,
+                FALSE,
+                &u4BufLen);
+        
+        if (rStatus != WLAN_STATUS_SUCCESS) {
+            DBGLOG(SEC, WARN, ("[wapi] set wapi assoc info error:%lx\n", rStatus));
+        }
+#endif
+#if CFG_SUPPORT_WPS2
+        if (wextSrchDesiredWPSIE(sme->ie,
+                    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:%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:%lx\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:%lx\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;
+        
+        kalMemSet(prWepKey, 0, sizeof(prWepKey));
+        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, WARN, ("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(INIT, INFO, ("wlanoidSetAddWep fail 0x%lx\n", rStatus));
+            return -EFAULT;
+        }
+    }
+
+    if(sme->ssid_len > 0) {
+        /* connect by SSID */
+        COPY_SSID(rNewSsid.aucSsid, rNewSsid.u4SsidLen, sme->ssid, sme->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:%lx\n", rStatus));
+            return -EINVAL;
+        }
+    }
+    else {
+        /* connect by BSSID */
+        rStatus = kalIoctl(prGlueInfo,
+                wlanoidSetBssid,
+                (PVOID) sme->bssid,
+                sizeof(MAC_ADDR_LEN),
+                FALSE,
+                FALSE,
+                TRUE,
+                FALSE,
+                &u4BufLen);
+
+        if (rStatus != WLAN_STATUS_SUCCESS) {
+            DBGLOG(REQ, WARN, ("set BSSID:%lx\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:%lx\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;
+
+    prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy);
+    ASSERT(prGlueInfo);
+
+    /* set channel */
+    if(params->channel) {
+        u4ChnlFreq = nicChannelNum2Freq(params->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:%lx\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:%lx\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:%lx\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(INIT, INFO, ("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(INIT, INFO, ("add pmkid error:%lx\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(INIT, INFO, ("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(INIT, INFO, ("flush pmkid error:%lx\n", rStatus));
+    }
+    kalMemFree(prPmkid, VIR_MEM_TYPE, 8);
+
+    return 0;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+ * @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 net_device *ndev,
+    struct ieee80211_channel *chan,
+    enum nl80211_channel_type channel_type,
+    unsigned int duration,
+    u64 *cookie
+    )
+{
+    P_GLUE_INFO_T prGlueInfo = NULL;
+
+    prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy);
+    ASSERT(prGlueInfo);
+
+#if 1
+    printk("--> %s()\n", __func__);
+#endif
+
+    /* not implemented */
+
+    return -EINVAL;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+ * @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 net_device *ndev,
+    u64 cookie
+    )
+{
+    P_GLUE_INFO_T prGlueInfo = NULL;
+
+    prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy);
+    ASSERT(prGlueInfo);
+
+#if 1
+    printk("--> %s()\n", __func__);
+#endif
+
+    /* not implemented */
+
+    return -EINVAL;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+ * @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 net_device *ndev,
+    struct ieee80211_channel *channel,
+    bool offscan,
+    enum nl80211_channel_type channel_type,
+    bool channel_type_valid,
+    unsigned int wait,
+    const u8 *buf,
+    size_t len,
+    bool no_cck,
+    bool dont_wait_for_ack,
+    u64 *cookie
+    )
+{
+    P_GLUE_INFO_T prGlueInfo = NULL;
+
+    prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy);
+    ASSERT(prGlueInfo);
+
+#if 1
+    printk("--> %s()\n", __func__);
+#endif
+
+    /* not implemented */
+
+    return -EINVAL;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+ * @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 net_device *ndev,
+    u64 cookie
+    )
+{
+    P_GLUE_INFO_T prGlueInfo = NULL;
+
+    prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy);
+    ASSERT(prGlueInfo);
+
+#if 1
+    printk("--> %s()\n", __func__);
+#endif
+
+    /* not implemented */
+
+    return -EINVAL;
+}
+
+
+#if CONFIG_NL80211_TESTMODE
+
+#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);
+       
+#if 1
+        printk("--> %s()\n", __func__);
+#endif
+
+    if(data && len) {
+        prParams = (P_NL80211_DRIVER_SET_KEY_EXTS)data;
+    }
+    
+    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 * 2);
+
+        /* 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_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
+        printk("--> %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;
+}
+
+int mtk_cfg80211_testmode_cmd(
+    IN struct wiphy *wiphy,
+    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;
+    BOOLEAN fgIsValid = 0;
+
+    ASSERT(wiphy);
+
+    prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy);
+
+#if 1
+    printk("--> %s()\n", __func__);
+#endif
+
+    if(data && len)
+        prParams = (P_NL80211_DRIVER_TEST_MODE_PARAMS)data;
+        
+    /* Clear the version byte */
+    prParams->index = prParams->index & ~ BITS(24,31);
+    
+    if(prParams){
+        switch(prParams->index){
+            case 1: /* SW cmd */
+                if(mtk_cfg80211_testmode_sw_cmd(wiphy, data, len))
+                    fgIsValid = TRUE;
+                break;
+            case 2: /* WAPI */
+#if CFG_SUPPORT_WAPI
+                if(mtk_cfg80211_testmode_set_key_ext(wiphy, data, len))
+                    fgIsValid = TRUE;
+#endif
+                break;
+            default:
+                fgIsValid = TRUE;
+                break;
+        }
+    }
+
+    return fgIsValid;
+}
+#endif
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_init.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_init.c
new file mode 100755 (executable)
index 0000000..30eee3d
--- /dev/null
@@ -0,0 +1,3144 @@
+/*
+** $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 $
+**
+** 11 15 2012 cp.wu
+** [ALPS00382763] N820_JB:[WIFI]N820JB WLAN ±K???,«ÝÉó?¬y¥\¯Ó¤j
+** do not try reconnecting when being disconnected by the peer
+ *
+ * 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 settting 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 similiar 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 continous memory demands
+ * separate kalMemAlloc() into virtually-continous and physically-continous 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 managment 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 "debug.h"
+#include "wlan_lib.h"
+#include "gl_wext.h"
+#include "gl_cfg80211.h"
+#include "precomp.h"
+
+/*******************************************************************************
+*                              C O N S T A N T S
+********************************************************************************
+*/
+//#define MAX_IOREQ_NUM   10
+
+BOOLEAN fgIsUnderEarlierSuspend = false;
+
+struct semaphore g_halt_sem;
+int g_u4HaltFlag = 0;
+
+
+/*******************************************************************************
+*                             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
+********************************************************************************
+*/
+
+MODULE_AUTHOR(NIC_AUTHOR);
+MODULE_DESCRIPTION(NIC_DESC);
+MODULE_SUPPORTED_DEVICE(NIC_NAME);
+/* WCNCR 00002676, 
+keep OS wake up for 100ms after sdio interrupt happen,
+make sure that RX & TX procedure isn't suspended
+*/
+KAL_WAKE_LOCK_T isr_wakelock;
+
+#if 0
+    MODULE_LICENSE("MTK Propietary");
+#else
+    MODULE_LICENSE("GPL");
+#endif
+
+#define NIC_INF_NAME    "wlan%d" /* interface name */
+
+#if DBG
+    UINT_8  aucDebugModule[DBG_MODULE_NUM];
+    UINT_32 u4DebugModule = 0;
+#endif /* DBG */
+
+//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 = 0; /* How many NICs coexist now */
+
+/*******************************************************************************
+*                           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
+
+#define CHAN2G(_channel, _freq, _flags)         \
+    {                                           \
+    .band               = IEEE80211_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               = IEEE80211_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),
+};
+
+/* 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 MT6620_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 MT6620_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            = MT6620_MCS_INFO,                  \
+}
+
+/* public for both Legacy Wi-Fi / P2P access */
+struct ieee80211_supported_band mtk_band_2ghz = {
+    .band       = IEEE80211_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     = MT6620_HT_CAP,
+};
+
+/* public for both Legacy Wi-Fi / P2P access */
+struct ieee80211_supported_band mtk_band_5ghz = {
+    .band       = IEEE80211_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     = MT6620_HT_CAP,
+};
+
+static const UINT_32 mtk_cipher_suites[] = {
+    /* 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
+};
+
+static struct cfg80211_ops mtk_wlan_ops = {
+    .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,
+    .get_station            = mtk_cfg80211_get_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,
+
+    /* 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,
+    #ifdef CONFIG_NL80211_TESTMODE
+    .testmode_cmd               = mtk_cfg80211_testmode_cmd,
+    #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
+********************************************************************************
+*/
+
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+extern int glRegisterEarlySuspend(
+    struct early_suspend        *prDesc,
+    early_suspend_callback      wlanSuspend,
+    late_resume_callback        wlanResume);
+
+extern int glUnregisterEarlySuspend(struct early_suspend *prDesc);
+#endif
+
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
+/*----------------------------------------------------------------------------*/
+/*!
+* \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)
+{
+    skb->priority = _cfg80211_classify8021d(skb);
+
+    return au16Wlan1dToQueueIdx[skb->priority];
+}
+#endif
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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
+        for (i = 0 ; i < sizeof(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));
+        }
+
+        // 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];
+                }
+            }
+        }
+    }
+    else {
+        prGlueInfo->fgNvramAvailable = FALSE;
+    }
+
+    return;
+}
+
+
+#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->u4Flag |= 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->u4Flag |= 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--;
+        }
+    }
+
+    return;
+} /* 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 WLAN_STATUS_SUCCESS The IOCTL command is executed successfully.
+* \retval OTHER 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, WARN, ("%s Invalid input data\n", __FUNCTION__));
+        return -EINVAL;
+    }
+
+    prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+    ASSERT(prGlueInfo);
+    if (!prGlueInfo) {
+        DBGLOG(INIT, WARN, ("%s No glue info\n", __FUNCTION__));
+        return -EFAULT;
+    }
+
+    if (prGlueInfo->u4ReadyFlag == 0) {
+        return -EINVAL;
+    }
+
+    printk ("ioctl %x\n", i4Cmd);
+
+    if (i4Cmd == SIOCGIWPRIV) {
+        /* 0x8B0D, get private ioctl table */
+        ret = wext_get_priv(prDev, prIFReq);
+    }
+    else 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 {
+        DBGLOG(INIT, WARN, ("Unexpected ioctl command: 0x%04x\n", i4Cmd));
+        /* return 0 for safe? */
+    }
+
+    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 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;
+
+    down(&g_halt_sem);
+    if (g_u4HaltFlag) {
+        up(&g_halt_sem);
+        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));
+        up(&g_halt_sem);
+        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) ||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+            (netdev_mc_count(prDev) > MAX_NUM_GROUP_ADDR)) {
+#else
+            (prDev->mc_count > MAX_NUM_GROUP_ADDR)) {
+#endif
+
+            u4PacketFilter |= PARAM_PACKET_FILTER_ALL_MULTICAST;
+        }
+        else {
+            u4PacketFilter |= PARAM_PACKET_FILTER_MULTICAST;
+        }
+    }
+
+    up(&g_halt_sem);
+
+    if (kalIoctl(prGlueInfo,
+            wlanoidSetCurrentPacketFilter,
+            &u4PacketFilter,
+            sizeof(u4PacketFilter),
+            FALSE,
+            FALSE,
+            TRUE,
+            FALSE,
+            &u4SetInfoLen) != WLAN_STATUS_SUCCESS) {
+        return;
+    }
+
+
+    if (u4PacketFilter & PARAM_PACKET_FILTER_MULTICAST) {
+        /* Prepare multicast address list */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+        struct netdev_hw_addr *ha;
+#else
+        struct dev_mc_list *prMcList;
+#endif
+        PUINT_8 prMCAddrList = NULL;
+        UINT_32 i = 0;
+
+        down(&g_halt_sem);
+        if (g_u4HaltFlag) {
+            up(&g_halt_sem);
+            return;
+        }
+
+        prMCAddrList = kalMemAlloc(MAX_NUM_GROUP_ADDR * ETH_ALEN, VIR_MEM_TYPE);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+        netdev_for_each_mc_addr(ha, prDev) {
+            if(i < MAX_NUM_GROUP_ADDR) {
+                memcpy((prMCAddrList + i * ETH_ALEN), ha->addr, ETH_ALEN);
+                i++;
+            }
+        }
+#else
+        for (i = 0, prMcList = prDev->mc_list;
+             (prMcList) && (i < prDev->mc_count) && (i < MAX_NUM_GROUP_ADDR);
+             i++, prMcList = prMcList->next) {
+            memcpy((prMCAddrList + i * ETH_ALEN), prMcList->dmi_addr, ETH_ALEN);
+        }
+#endif
+
+        up(&g_halt_sem);
+
+        kalIoctl(prGlueInfo,
+            wlanoidSetMulticastList,
+            prMCAddrList,
+            (i * ETH_ALEN),
+            FALSE,
+            FALSE,
+            TRUE,
+            FALSE,
+            &u4SetInfoLen);
+
+        kalMemFree(prMCAddrList, VIR_MEM_TYPE, MAX_NUM_GROUP_ADDR * ETH_ALEN);
+    }
+
+    return;
+} /* end of wlanSetMulticastList() */
+
+
+/* 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) {
+
+    ASSERT(prGlueInfo);
+
+    if (!prGlueInfo) {
+        DBGLOG(INIT, WARN, ("abnormal dev or skb: prGlueInfo(0x%p)\n",
+            prGlueInfo));
+        return;
+    }
+
+#if CFG_ENABLE_WIFI_DIRECT
+    if(prGlueInfo->prAdapter->fgIsP2PRegistered) {
+        mtk_p2p_wext_set_Multicastlist(prGlueInfo);
+    }
+#endif
+
+    return;
+} /* end of p2pSetMulticastListWorkQueueWrapper() */
+
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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_BOW_TEST
+    UINT_32 i;
+#endif
+
+    GLUE_SPIN_LOCK_DECLARATION();
+
+    ASSERT(prSkb);
+    ASSERT(prDev);
+    ASSERT(prGlueInfo);
+
+    if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) {
+        DBGLOG(INIT, INFO, ("GLUE_FLAG_HALT skip tx\n"));
+        dev_kfree_skb(prSkb);
+        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, ("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) {
+
+    #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
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 26)
+        u2QueueIdx = skb_get_queue_mapping(prSkb);
+        ASSERT(u2QueueIdx < CFG_MAX_TXQ_NUM);
+#endif
+
+       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 LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 26)
+        if (prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_AIS_INDEX][u2QueueIdx] >= CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD) {
+            netif_stop_subqueue(prDev, u2QueueIdx);
+        }
+#else
+        if (prGlueInfo->i4TxPendingFrameNum >= CFG_TX_STOP_NETIF_QUEUE_THRESHOLD) {
+            netif_stop_queue(prDev);
+        }
+#endif
+    } 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++;
+
+    //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 (!prDev) {
+        return -ENXIO;
+    }
+
+    prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 12)
+    INIT_DELAYED_WORK(&workq, wlanSetMulticastListWorkQueue);
+#else
+    INIT_DELAYED_WORK(&workq, wlanSetMulticastListWorkQueue, NULL);
+#endif
+
+    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
+    )
+{
+    return;
+} /* 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);
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 26)
+    netif_tx_start_all_queues(prDev);
+#else
+    netif_start_queue(prDev);
+#endif
+
+    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;
+    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, TRUE);
+    }
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 26)
+    netif_tx_stop_all_queues(prDev);
+#else
+    netif_stop_queue(prDev);
+#endif
+
+    return 0; /* success */
+} /* end of wlanStop() */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+ * \brief Update Channel table for cfg80211 for Wi-Fi Direct based on current country code
+ *
+ * \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 channel
+    for(i = 0; i < ARRAY_SIZE(mtk_2ghz_channels); i++) {
+        mtk_2ghz_channels[i].flags |= IEEE80211_CHAN_DISABLED;
+    }
+
+    for(i = 0; i < ARRAY_SIZE(mtk_5ghz_channels); i++) {
+        mtk_5ghz_channels[i].flags |= IEEE80211_CHAN_DISABLED;
+    }
+
+    // 2. Get current domain channel list
+    rlmDomainGetChnlList(prGlueInfo->prAdapter,
+            BAND_NULL,
+            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;
+                    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;
+                    break;
+                }
+            }
+            break;
+            
+        default:
+            break;
+        }
+    }
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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);
+
+        if ((i4DevIdx = wlanGetDevIdx(prWdev->netdev)) < 0) {
+            DBGLOG(INIT, ERROR, ("wlanNetRegister: net_device number exceeds.\n"));
+            break;
+        }
+
+        /* adjust channel support status */
+        wlanUpdateChannelTable((P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy));
+
+        if (wiphy_register(prWdev->wiphy) < 0) {
+            DBGLOG(INIT, ERROR, ("wlanNetRegister: wiphy context is not registered.\n"));
+            wlanClearDevIdx(prWdev->netdev);
+            i4DevIdx = -1;
+        }
+
+        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;
+        }
+
+        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;
+    }
+
+    prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy);
+
+    wlanClearDevIdx(prWdev->netdev);
+    unregister_netdev(prWdev->netdev);
+    wiphy_unregister(prWdev->wiphy);
+
+    prGlueInfo->fgIsRegistered = FALSE;
+
+    DBGLOG(INIT, INFO, ("unregister wireless_dev(0x%p)\n", prWdev));
+
+    return;
+} /* end of wlanNetUnregister() */
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
+static const struct net_device_ops wlan_netdev_ops = {
+       .ndo_open               = wlanOpen,
+       .ndo_stop               = wlanStop,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+    .ndo_set_rx_mode = wlanSetMulticastList,
+#else
+       .ndo_set_multicast_list = wlanSetMulticastList,
+#endif
+       .ndo_get_stats          = wlanGetStats,
+       .ndo_do_ioctl           = wlanDoIOCTL,
+       .ndo_start_xmit         = wlanHardStartXmit,
+       .ndo_init               = wlanInit,
+       .ndo_uninit             = wlanUninit,
+    .ndo_select_queue = wlanSelectQueue,
+};
+#endif
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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
+    )
+{
+    struct wireless_dev *prWdev = NULL;
+    P_GLUE_INFO_T prGlueInfo =  NULL;
+    P_ADAPTER_T prAdapter = NULL;
+    UINT_32 i;
+    struct device *prDev;
+
+    //4 <1.1> Create wireless_dev
+    prWdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
+    DBGLOG(INIT, INFO, ("wireless_dev prWdev(0x%p) allocated\n", prWdev));
+    if (!prWdev) {
+        DBGLOG(INIT, ERROR, ("Allocating memory to wireless_dev context failed\n"));
+        return NULL;
+    }
+
+    //4 <1.2> Create wiphy
+    prWdev->wiphy = wiphy_new(&mtk_wlan_ops, sizeof(GLUE_INFO_T));
+    DBGLOG(INIT, INFO, ("wiphy (0x%p) allocated\n", prWdev->wiphy));
+    if (!prWdev->wiphy) {
+        DBGLOG(INIT, ERROR, ("Allocating memory to wiphy device failed\n"));
+        kfree(prWdev);
+        return NULL;
+    }
+
+    //4 <1.3> 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;
+#endif
+    if (!prDev) {
+        printk(KERN_ALERT DRV_NAME "unable to get struct dev for wlan\n");
+    }
+    set_wiphy_dev(prWdev->wiphy, prDev);
+
+    //4 <1.4> configure wireless_dev & wiphy
+    prWdev->iftype = NL80211_IFTYPE_STATION;
+    prWdev->wiphy->max_scan_ssids   = 1;    /* FIXME: for combo scan */
+    prWdev->wiphy->max_scan_ie_len = 512;
+    prWdev->wiphy->interface_modes  = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC);
+    prWdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &mtk_band_2ghz;
+    prWdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &mtk_band_5ghz;
+    prWdev->wiphy->signal_type      = CFG80211_SIGNAL_TYPE_MBM;
+    prWdev->wiphy->cipher_suites    = (const u32 *)mtk_cipher_suites;
+    prWdev->wiphy->n_cipher_suites  = ARRAY_SIZE(mtk_cipher_suites);
+    #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) 
+    prWdev->wiphy->flags            = WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_SUPPORTS_FW_ROAM;
+    #else
+    prWdev->wiphy->flags            = WIPHY_FLAG_CUSTOM_REGULATORY;
+    #endif     
+
+    //4 <2> Create Glue structure
+    prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy);
+    if (!prGlueInfo) {
+        DBGLOG(INIT, ERROR, ("Allocating memory to glue layer failed\n"));
+        goto netcreate_err;
+    }
+
+    //4 <3> Initial Glue structure
+    //4 <3.1> create net device 
+    prGlueInfo->prDevHandler = alloc_netdev_mq(sizeof(P_GLUE_INFO_T), NIC_INF_NAME, ether_setup, CFG_MAX_TXQ_NUM);
+
+    DBGLOG(INIT, INFO, ("net_device prDev(0x%p) allocated\n", prGlueInfo->prDevHandler));
+    if (!prGlueInfo->prDevHandler) {
+        DBGLOG(INIT, ERROR, ("Allocating memory to net_device context failed\n"));
+        goto netcreate_err;
+    }
+
+    //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));
+
+    //4 <3.2> initiali glue variables 
+    prGlueInfo->eParamMediaStateIndicated = PARAM_MEDIA_STATE_DISCONNECTED;
+    prGlueInfo->ePowerState = ParamDeviceStateD0;
+    prGlueInfo->fgIsMacAddrOverride = FALSE;
+    prGlueInfo->fgIsRegistered = FALSE;
+    prGlueInfo->prScanRequest = NULL;
+
+    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);
+
+    /* initialize semaphore for ioctl */
+    sema_init(&g_halt_sem, 1);
+    g_u4HaltFlag = 0;
+
+    //4 <4> Create Adapter structure
+    prAdapter = (P_ADAPTER_T) wlanAdapterCreate(prGlueInfo);
+
+    if (!prAdapter) {
+        DBGLOG(INIT, ERROR, ("Allocating memory to adapter failed\n"));
+        goto netcreate_err;
+    }
+
+    prGlueInfo->prAdapter = prAdapter;
+
+#ifdef CONFIG_CFG80211_WEXT
+    //4 <5> Use wireless extension to replace IOCTL
+    prWdev->wiphy->wext = &wext_handler_def;
+#endif
+
+    goto netcreate_done;
+
+netcreate_err:
+    if (NULL != prAdapter) {
+        wlanAdapterDestroy(prAdapter);
+        prAdapter = NULL;
+    }
+
+    if (NULL != prGlueInfo->prDevHandler) {
+        free_netdev(prGlueInfo->prDevHandler);
+        prGlueInfo->prDevHandler = NULL;
+    }
+
+    if (NULL != prWdev->wiphy) {
+        wiphy_free(prWdev->wiphy);
+        prWdev->wiphy = NULL;
+    }
+
+    if (NULL != prWdev) {
+        /* Free net_device and private data, which are allocated by
+         * alloc_netdev().
+         */
+        kfree(prWdev);
+        prWdev = NULL;
+    }
+
+netcreate_done:
+
+    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;
+
+    /* Free net_device and private data, which are allocated by alloc_netdev().
+     */
+    free_netdev(prWdev->netdev);
+    wiphy_free(prWdev->wiphy);
+
+    kfree(prWdev);
+
+    return;
+} /* end of wlanNetDestroy() */
+
+#ifndef CONFIG_X86
+UINT_8 g_aucBufIpAddr[32] = {0};
+
+static void wlanEarlySuspend(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;
+
+    DBGLOG(INIT, INFO, ("*********wlanEarlySuspend************\n"));
+
+    // <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;
+    ASSERT(prDev);
+
+fgIsUnderEarlierSuspend = true;
+
+    // <2> 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(INIT, INFO, ("ip is not avaliable.\n"));
+        return;
+    }
+
+    // <3> acquire the prGlueInfo
+    prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+    ASSERT(prGlueInfo);
+
+    // <4> copy the IPv4 address
+    kalMemCopy(ip, &(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local), sizeof(ip));
+    DBGLOG(INIT, 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
+    // <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(INIT, INFO, ("ipv6 is not avaliable.\n"));
+        return;
+    }
+    // <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]
+            ));
+
+    // 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
+
+    // <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 + u4NumIPv6;
+        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));
+            u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(PARAM_NETWORK_ADDRESS);
+#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));
+            u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip6);
+       }
+#endif
+        ASSERT(u4Len <= sizeof(g_aucBufIpAddr/*aucBuf*/));
+
+        rStatus = kalIoctl(prGlueInfo,
+                wlanoidSetNetworkAddress,
+                (PVOID)prParamNetAddrList,
+                u4Len,
+                FALSE,
+                FALSE,
+                TRUE,
+                FALSE,
+                &u4SetInfoLen);
+
+        if (rStatus != WLAN_STATUS_SUCCESS) {
+            DBGLOG(INIT, INFO, ("set HW pattern filter fail 0x%lx\n", rStatus));
+        }
+    }
+}
+
+static void wlanLateResume(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
+
+    DBGLOG(INIT, INFO, ("*********wlanLateResume************\n"));
+
+    // <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);
+
+fgIsUnderEarlierSuspend = false;
+
+    // <2> 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(INIT, INFO, ("ip is not avaliable.\n"));
+        return;
+    }
+
+    // <3> acquire the prGlueInfo
+    prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+    ASSERT(prGlueInfo);
+
+    // <4> copy the IPv4 address
+    kalMemCopy(ip, &(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local), sizeof(ip));
+    DBGLOG(INIT, INFO, ("ip is %d.%d.%d.%d\n",
+            ip[0],ip[1],ip[2],ip[3]));
+
+#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(INIT, INFO, ("ipv6 is not avaliable.\n"));
+        return;
+    }
+    // <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
+    {
+        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,
+                wlanoidSetNetworkAddress,
+                (PVOID)prParamNetAddrList,
+                u4Len,
+                FALSE,
+                FALSE,
+                TRUE,
+                FALSE,
+                &u4SetInfoLen);
+
+        if (rStatus != WLAN_STATUS_SUCCESS) {
+            DBGLOG(INIT, INFO, ("set HW pattern filter fail 0x%lx\n", rStatus));
+        }
+    }
+}
+
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+static struct early_suspend mt6620_early_suspend_desc = {
+    .level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN,
+};
+
+static void wlan_early_suspend(struct early_suspend *h)
+{
+    DBGLOG(INIT, INFO, ("*********wlan_early_suspend************\n"));
+    wlanEarlySuspend();
+}
+
+static void wlan_late_resume(struct early_suspend *h)
+{
+    DBGLOG(INIT, INFO, ("*********wlan_late_resume************\n"));
+    wlanLateResume();
+}
+#endif //defined(CONFIG_HAS_EARLYSUSPEND)
+#endif //! CONFIG_X86
+
+extern void wlanRegisterNotifier(void);
+extern void wlanUnregisterNotifier(void);
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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;
+    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;
+    BOOL bRet = FALSE;
+
+
+    do {
+#if DBG
+        int i;
+        /* Initialize DEBUG CLASS of each module */
+        for (i = 0; i < DBG_MODULE_NUM; i++) {
+            aucDebugModule[i] = DBG_CLASS_ERROR | \
+                                DBG_CLASS_WARN | \
+                                DBG_CLASS_STATE | \
+                                DBG_CLASS_TRACE | \
+                                DBG_CLASS_EVENT;
+            //aucDebugModule[i] = 0;
+        }
+#if 0
+        aucDebugModule[DBG_INIT_IDX] |= DBG_CLASS_TRACE | DBG_CLASS_INFO;
+        aucDebugModule[DBG_ARB_IDX] |= DBG_CLASS_TRACE | DBG_CLASS_INFO;
+        aucDebugModule[DBG_JOIN_IDX] |= DBG_CLASS_TRACE | DBG_CLASS_INFO;
+        //aucDebugModule[DBG_RX_IDX] |= DBG_CLASS_TRACE | DBG_CLASS_INFO;
+        aucDebugModule[DBG_TX_IDX] |= DBG_CLASS_TRACE | DBG_CLASS_INFO;
+        aucDebugModule[DBG_NIC_IDX] |= DBG_CLASS_TRACE | DBG_CLASS_INFO;
+        aucDebugModule[DBG_HAL_IDX] |= DBG_CLASS_TRACE | DBG_CLASS_INFO;
+        aucDebugModule[DBG_KEVIN_IDX] |= DBG_CLASS_TRACE | DBG_CLASS_INFO | DBG_CLASS_TEMP;
+        aucDebugModule[DBG_SCAN_IDX] |= DBG_CLASS_TRACE | DBG_CLASS_INFO;
+        aucDebugModule[DBG_REQ_IDX] |= DBG_CLASS_TRACE | DBG_CLASS_INFO;
+        //aucDebugModule[DBG_MGT_IDX] |= DBG_CLASS_TRACE | DBG_CLASS_INFO;
+        aucDebugModule[DBG_RSN_IDX] |= DBG_CLASS_TRACE;
+        aucDebugModule[DBG_ROAMING_IDX] |= DBG_CLASS_TRACE | DBG_CLASS_INFO;
+#endif
+#endif /* DBG */
+
+        //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);
+
+        /* Cannot get IO address from interface */
+        if (FALSE == bRet) {
+            DBGLOG(INIT, ERROR, (KERN_ALERT "wlanProbe: glBusInit() fail\n"));
+            i4Status = -EIO;
+            break;
+        }
+
+        //4 <2> Create network device, Adapter, KalInfo, prDevHandler(netdev)
+        if ((prWdev = wlanNetCreate(pvData)) == NULL) {
+            DBGLOG(INIT, ERROR, ("wlanProbe: No memory for dev and its private\n"));
+            i4Status = -ENOMEM;
+            break;
+        }
+
+        //4 <2.5> Set the ioaddr to HIF Info
+        prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy);
+        gPrDev = prGlueInfo->prDevHandler;
+        glSetHifInfo(prGlueInfo, (UINT_32) pvData);
+
+
+        /* main thread is created in this function */
+        init_waitqueue_head(&prGlueInfo->waitq);
+        //
+
+        QUEUE_INITIALIZE(&prGlueInfo->rCmdQueue);
+        QUEUE_INITIALIZE(&prGlueInfo->rTxQueue);
+
+
+
+        //prGlueInfo->main_thread = kthread_run(tx_thread, prGlueInfo->prDevHandler, "tx_thread");
+
+        //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"));
+            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
+
+        //4 <5> Start Device
+        //
+#if CFG_ENABLE_FW_DOWNLOAD
+        /* 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);
+
+            //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;
+                goto bailout;
+            } else {
+                if (wlanAdapterStart(prAdapter, prRegInfo,  prFwBuffer, u4FwSize) != WLAN_STATUS_SUCCESS) {
+                    i4Status = -EIO;
+                }
+            }
+
+            kalFirmwareImageUnmapping(prGlueInfo, NULL, prFwBuffer);
+
+bailout:
+            //kfree(prRegInfo);
+
+            if (i4Status < 0) {
+                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;
+            break;
+        }
+#endif
+       if(TRUE == prAdapter->fgEnable5GBand)
+               prWdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &mtk_band_5ghz;
+
+        prGlueInfo->main_thread = kthread_run(tx_thread, prGlueInfo->prDevHandler, "tx_thread");
+
+        /* set MAC address */
+        {
+            WLAN_STATUS rStatus = WLAN_STATUS_FAILURE;
+            struct sockaddr MacAddr;
+            UINT_32 u4SetInfoLen = 0;
+
+            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%lx\n", rStatus));
+                prGlueInfo->u4ReadyFlag = 0;
+            } else {
+                memcpy(prGlueInfo->prDevHandler->dev_addr, &MacAddr.sa_data, ETH_ALEN);
+                memcpy(prGlueInfo->prDevHandler->perm_addr, prGlueInfo->prDevHandler->dev_addr, ETH_ALEN);
+
+                /* card is ready */
+                prGlueInfo->u4ReadyFlag = 1;
+#if CFG_SHOW_MACADDR_SOURCE
+                DBGLOG(INIT, INFO, ("MAC address: "MACSTR, MAC2STR(&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%lx\n", rStatus));
+            }
+        }
+#endif
+
+        //4 <3> Register the card
+        if ((i4DevIdx = wlanNetRegister(prWdev)) < 0){
+            i4Status = -ENXIO;
+            DBGLOG(INIT, ERROR, ("wlanProbe: Cannot register the net_device context to the kernel\n"));
+            break;
+        }
+
+        glRegisterEarlySuspend(&mt6620_early_suspend_desc, wlan_early_suspend, wlan_late_resume);
+        wlanRegisterNotifier();
+
+
+        //4 <6> Initialize /proc filesystem
+#ifdef WLAN_INCLUDE_PROC
+        if ( (i4Status = procInitProcfs(prDev, NIC_DEVICE_ID_LOW)) < 0) {
+            DBGLOG(INIT, ERROR, ("wlanProbe: init procfs failed\n"));
+            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
+        /*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);
+        }
+#endif
+    }
+    while (FALSE);
+
+    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
+    )
+{
+    struct net_device *prDev = NULL;
+    P_WLANDEV_INFO_T prWlandevInfo = NULL;
+    P_GLUE_INFO_T prGlueInfo = NULL;
+    P_ADAPTER_T prAdapter = NULL;
+
+    DBGLOG(INIT, INFO, ("Remove wlan!\n"));
+
+
+    //4 <0> Sanity check
+    ASSERT(u4WlanDevNum <= CFG_MAX_WLAN_DEVICES);
+    if (0 == u4WlanDevNum) {
+        DBGLOG(INIT, INFO, ("0 == u4WlanDevNum\n"));
+        return;
+    }
+
+    prDev = arWlanDevInfo[u4WlanDevNum-1].prDev;
+    prWlandevInfo = &arWlanDevInfo[u4WlanDevNum-1];
+
+    ASSERT(prDev);
+    if (NULL == prDev) {
+        DBGLOG(INIT, INFO, ("NULL == prDev\n"));
+        return;
+    }
+
+    prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+    ASSERT(prGlueInfo);
+    if (NULL == prGlueInfo) {
+        DBGLOG(INIT, INFO, ("NULL == prGlueInfo\n"));
+        free_netdev(prDev);
+        return;
+    }
+
+
+#if CFG_ENABLE_WIFI_DIRECT
+    prGlueInfo->prAdapter->fgIsWlanLaunched = FALSE;
+    if(prGlueInfo->prAdapter->fgIsP2PRegistered) {
+        p2pNetUnregister(prGlueInfo, FALSE);
+        p2pRemove(prGlueInfo);
+    }
+
+#if 0
+    prGlueInfo->prAdapter->fgIsWlanLaunched = FALSE;
+    //if(prGlueInfo->prAdapter->fgIsP2PRegistered) {
+    if (prGlueInfo->prP2PInfo) {
+        //p2pRemove(prGlueInfo);
+        if (prGlueInfo->prP2PInfo->prDevHandler) {
+            free_netdev(prGlueInfo->prP2PInfo->prDevHandler);
+            prGlueInfo->prP2PInfo->prDevHandler = NULL;
+
+        }
+
+
+        if(!p2PFreeInfo(prGlueInfo)) {
+           printk(KERN_ALERT DRV_NAME "Free memory for p2p FAILED\n");
+           ASSERT(0);
+           return;
+        }
+    }
+#endif
+#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
+    glBusFreeIrq(prDev, *((P_GLUE_INFO_T *) netdev_priv(prDev)));
+
+    kalMemSet(&(prGlueInfo->prAdapter->rWlanInfo), 0, sizeof(WLAN_INFO_T));
+
+    flush_delayed_work_sync(&workq);
+
+    down(&g_halt_sem);
+    g_u4HaltFlag = 1;
+
+    //4 <2> Mark HALT, notify main thread to stop, and clean up queued requests
+    prGlueInfo->u4Flag |= GLUE_FLAG_HALT;
+    /* wake up main thread */
+    wake_up_interruptible(&prGlueInfo->waitq);
+    /* wait main thread stops */
+    wait_for_completion_interruptible(&prGlueInfo->rHaltComp);
+
+    DBGLOG(INIT, INFO, ("mtk_sdiod stopped\n"));
+
+    //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(prDev, NIC_DEVICE_ID_LOW);
+#endif /* WLAN_INCLUDE_PROC */
+
+    //4 <4> wlanAdapterStop
+    prAdapter = prGlueInfo->prAdapter;
+
+    wlanAdapterStop(prAdapter);
+    DBGLOG(INIT, INFO, ("Number of Stalled Packets = %ld\n", prGlueInfo->i4TxPendingFrameNum));
+
+    //4 <5> Release the Bus
+    glBusRelease(prDev);
+
+    up(&g_halt_sem);
+
+    //4 <6> Unregister the card
+    wlanNetUnregister(prDev->ieee80211_ptr);
+
+    //4 <7> Destroy the device
+    wlanNetDestroy(prDev->ieee80211_ptr);
+    prDev = NULL;
+
+
+    glUnregisterEarlySuspend(&mt6620_early_suspend_desc);
+    wlanUnregisterNotifier();
+
+    return;
+} /* 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 __init initWlan(void)
+{
+    int ret = 0;
+
+    DBGLOG(INIT, INFO, ("initWlan\n"));
+
+    /* memory pre-allocation */
+    kalInitIOBuffer();
+
+    //return ((glRegisterBus(wlanProbe, wlanRemove) == WLAN_STATUS_SUCCESS) ? 0: -EIO);
+    ret = ((glRegisterBus(wlanProbe, wlanRemove) == WLAN_STATUS_SUCCESS) ? 0: -EIO);
+
+    if (ret == -EIO) {
+        kalUninitIOBuffer();
+        return ret;
+    }
+
+#if (CFG_CHIP_RESET_SUPPORT)
+    glResetInit();
+#endif
+
+    /*WCNCR00002676, keep OS wake up for 100ms*/
+    KAL_WAKE_LOCK_INIT(NULL, &isr_wakelock, "WLAN TIME 2");
+    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 __exit exitWlan(void)
+{
+    //printk("remove %p\n", wlanRemove);
+#if CFG_CHIP_RESET_SUPPORT
+    glResetUninit();
+#endif
+
+    glUnregisterBus(wlanRemove);
+
+    /*WCNCR00002676*/
+    KAL_WAKE_LOCK_DESTROY(NULL, &isr_wakelock);
+    /* free pre-allocated memory */
+    kalUninitIOBuffer();
+
+    DBGLOG(INIT, INFO, ("exitWlan\n"));
+
+    return;
+} /* end of exitWlan() */
+
+module_init(initWlan);
+module_exit(exitWlan);
+#if 0
+/* export necessary symbol for p2p driver using */
+#if CFG_ENABLE_WIFI_DIRECT
+EXPORT_SYMBOL(wlanSubModRegisterInitExit);
+EXPORT_SYMBOL(wlanSubModExit);
+EXPORT_SYMBOL(wlanSubModInit);
+
+EXPORT_SYMBOL(nicPmIndicateBssCreated);
+EXPORT_SYMBOL(rlmProcessAssocRsp);
+EXPORT_SYMBOL(kalSetEvent);
+EXPORT_SYMBOL(rlmBssInitForAPandIbss);
+EXPORT_SYMBOL(kalEnqueueCommand);
+EXPORT_SYMBOL(nicIncreaseTxSeqNum);
+EXPORT_SYMBOL(nicCmdEventQueryAddress);
+EXPORT_SYMBOL(bssCreateStaRecFromBssDesc);
+EXPORT_SYMBOL(rlmBssAborted);
+EXPORT_SYMBOL(cnmStaRecResetStatus);
+EXPORT_SYMBOL(mqmProcessAssocRsp);
+EXPORT_SYMBOL(nicTxReturnMsduInfo);
+EXPORT_SYMBOL(nicTxEnqueueMsdu);
+EXPORT_SYMBOL(wlanProcessSecurityFrame);
+EXPORT_SYMBOL(nicChannelNum2Freq);
+EXPORT_SYMBOL(nicUpdateBss);
+EXPORT_SYMBOL(wlanSendSetQueryCmd);
+EXPORT_SYMBOL(cnmStaRecAlloc);
+EXPORT_SYMBOL(cnmTimerInitTimer);
+EXPORT_SYMBOL(rateGetRateSetFromIEs);
+EXPORT_SYMBOL(nicOidCmdTimeoutCommon);
+EXPORT_SYMBOL(cnmStaRecChangeState);
+EXPORT_SYMBOL(rateGetDataRatesFromRateSet);
+EXPORT_SYMBOL(cnmMgtPktAlloc);
+EXPORT_SYMBOL(cnmMgtPktFree);
+EXPORT_SYMBOL(wextSrchDesiredWPAIE);
+EXPORT_SYMBOL(nicRxReturnRFB);
+EXPORT_SYMBOL(cnmTimerStartTimer);
+EXPORT_SYMBOL(cmdBufAllocateCmdInfo);
+EXPORT_SYMBOL(cnmGetStaRecByAddress);
+EXPORT_SYMBOL(nicMediaStateChange);
+EXPORT_SYMBOL(bssUpdateBeaconContent);
+EXPORT_SYMBOL(kalIoctl);
+EXPORT_SYMBOL(nicActivateNetwork);
+EXPORT_SYMBOL(nicDeactivateNetwork);
+EXPORT_SYMBOL(kalRandomNumber);
+EXPORT_SYMBOL(nicCmdEventSetCommon);
+EXPORT_SYMBOL(cnmTimerStopTimer);
+EXPORT_SYMBOL(nicIncreaseCmdSeqNum);
+EXPORT_SYMBOL(authSendDeauthFrame);
+EXPORT_SYMBOL(cnmMemAlloc);
+EXPORT_SYMBOL(nicPmIndicateBssAbort);
+EXPORT_SYMBOL(nicCmdEventSetIpAddress);
+EXPORT_SYMBOL(mboxSendMsg);
+EXPORT_SYMBOL(scanSearchBssDescByBssid);
+EXPORT_SYMBOL(bssRemoveStaRecFromClientList);
+EXPORT_SYMBOL(assocProcessRxDisassocFrame);
+EXPORT_SYMBOL(authProcessRxDeauthFrame);
+EXPORT_SYMBOL(cnmStaRecFree);
+EXPORT_SYMBOL(rNonHTPhyAttributes);
+EXPORT_SYMBOL(rNonHTApModeAttributes);
+EXPORT_SYMBOL(cnmMemFree);
+EXPORT_SYMBOL(wlanExportGlueInfo);
+EXPORT_SYMBOL(bssInitForAP);
+EXPORT_SYMBOL(nicPmIndicateBssConnected);
+EXPORT_SYMBOL(rlmRspGenerateHtOpIE);
+EXPORT_SYMBOL(bssGenerateExtSuppRate_IE);
+EXPORT_SYMBOL(rlmRspGenerateErpIE);
+EXPORT_SYMBOL(rlmRspGenerateHtCapIE);
+EXPORT_SYMBOL(cnmGetStaRecByIndex);
+EXPORT_SYMBOL(rsnGenerateWpaNoneIE);
+EXPORT_SYMBOL(rlmRspGenerateExtCapIE);
+EXPORT_SYMBOL(rsnGenerateRSNIE);
+EXPORT_SYMBOL(rsnParseRsnIE);
+#if CFG_SUPPORT_WPS
+EXPORT_SYMBOL(wextSrchDesiredWPSIE);
+#endif
+EXPORT_SYMBOL(mboxDummy);
+EXPORT_SYMBOL(saaFsmRunEventStart);
+EXPORT_SYMBOL(saaFsmRunEventAbort);
+EXPORT_SYMBOL(cnmP2PIsPermitted);
+EXPORT_SYMBOL(cnmBss40mBwPermitted);
+EXPORT_SYMBOL(mqmGenerateWmmParamIE);
+EXPORT_SYMBOL(cnmPreferredChannel);
+EXPORT_SYMBOL(bssAddStaRecToClientList);
+EXPORT_SYMBOL(nicQmUpdateWmmParms);
+EXPORT_SYMBOL(qmFreeAllByNetType);
+EXPORT_SYMBOL(wlanQueryInformation);
+EXPORT_SYMBOL(nicConfigPowerSaveProfile);
+EXPORT_SYMBOL(scanSearchExistingBssDesc);
+EXPORT_SYMBOL(scanAllocateBssDesc);
+EXPORT_SYMBOL(wlanProcessCommandQueue);
+EXPORT_SYMBOL(wlanAcquirePowerControl);
+EXPORT_SYMBOL(wlanReleasePowerControl);
+EXPORT_SYMBOL(wlanReleasePendingCMDbyNetwork);
+#if DBG
+EXPORT_SYMBOL(aucDebugModule);
+EXPORT_SYMBOL(fgIsBusAccessFailed);
+EXPORT_SYMBOL(allocatedMemSize);
+EXPORT_SYMBOL(dumpMemory8);
+EXPORT_SYMBOL(dumpMemory32);
+#endif
+EXPORT_SYMBOL(rlmDomainIsLegalChannel);
+EXPORT_SYMBOL(scnQuerySparseChannel);
+EXPORT_SYMBOL(rlmDomainGetChnlList);
+EXPORT_SYMBOL(p2pSetMulticastListWorkQueueWrapper);
+EXPORT_SYMBOL(nicUpdateRSSI);
+EXPORT_SYMBOL(nicCmdEventQueryLinkQuality);
+EXPORT_SYMBOL(kalGetMediaStateIndicated);
+EXPORT_SYMBOL(nicFreq2ChannelNum);
+EXPORT_SYMBOL(assocSendDisAssocFrame);
+EXPORT_SYMBOL(nicUpdateBeaconIETemplate);
+EXPORT_SYMBOL(rsnParseCheckForWFAInfoElem);
+EXPORT_SYMBOL(kalClearMgmtFramesByNetType);
+EXPORT_SYMBOL(kalClearSecurityFramesByNetType);
+EXPORT_SYMBOL(nicFreePendingTxMsduInfoByNetwork);
+EXPORT_SYMBOL(bssComposeBeaconProbeRespFrameHeaderAndFF);
+EXPORT_SYMBOL(bssBuildBeaconProbeRespFrameCommonIEs);
+EXPORT_SYMBOL(wlanoidSetWapiAssocInfo);
+EXPORT_SYMBOL(wlanoidSetWSCAssocInfo);
+#endif
+#endif
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_kal.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_kal.c
new file mode 100755 (executable)
index 0000000..0063f51
--- /dev/null
@@ -0,0 +1,3982 @@
+/*
+** $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 similiar 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 availble 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 managment 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
+**  <workaround> 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 "gl_os.h"
+#include "gl_wext.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
+********************************************************************************
+*/
+#if DBG
+int allocatedMemSize = 0;
+#endif
+
+extern struct semaphore g_halt_sem;
+extern int g_u4HaltFlag;
+
+/*******************************************************************************
+*                           P R I V A T E   D A T A
+********************************************************************************
+*/
+static PVOID pvIoBuffer = NULL;
+static UINT_32 pvIoBufferSize = 0;
+static UINT_32 pvIoBufferUsage = 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;
+
+extern ENUM_WMTHWVER_TYPE_T
+mtk_wcn_wmt_hwver_get(
+    VOID
+    );
+#elif defined(MT5931) && CFG_MULTI_ECOVER_SUPPORT
+typedef enum _ENUM_HWVER_TYPE_T{
+    HWVER_MT5931_E1 = 0x1,
+    HWVER_MT5931_E2 = 0x2,
+    HWVER_MT5931_E3 = 0x3,
+    HWVER_MT5931_MAX,
+    HWVER_INVALID = 0xff
+} ENUM_HWVER_TYPE_T, *P_ENUM_HWVER_TYPE_T;
+#endif
+
+
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+#if CFG_ENABLE_FW_DOWNLOAD
+
+static struct file *filp = NULL;
+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
+    )
+{
+    /* 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) */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29))
+    orgfsuid = current->fsuid;
+    orgfsgid = current->fsgid;
+    current->fsuid = current->fsgid = 0;
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
+    struct cred *cred = (struct cred *) get_current_cred();
+    orgfsuid = cred->fsuid;
+    orgfsgid = cred->fsgid;
+    cred->fsuid = cred->fsgid = 0;
+#else
+    struct cred *cred = get_task_cred(current);
+    orgfsuid = cred->fsuid;
+    orgfsgid = cred->fsgid;
+    cred->fsuid = cred->fsgid = 0;
+#endif
+
+    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(MT5931) && CFG_MULTI_ECOVER_SUPPORT
+    switch (wlanGetEcoVersion(prGlueInfo->prAdapter)) {
+    case HWVER_MT5931_E1:
+    case HWVER_MT5931_E2:
+        filp = filp_open("/etc/firmware/"CFG_FW_FILENAME"_E2", O_RDONLY, 0);
+        break;
+    case HWVER_MT5931_E3:
+    default:
+        filp = filp_open("/etc/firmware/"CFG_FW_FILENAME, O_RDONLY, 0);
+        break;
+    }
+#elif defined(MT6628)
+    filp = filp_open("/etc/firmware/"CFG_FW_FILENAME"_MT6628", O_RDONLY, 0);
+#else
+    filp = filp_open("/etc/firmware/"CFG_FW_FILENAME, O_RDONLY, 0);
+#endif
+    if (IS_ERR(filp)) {
+        DBGLOG(INIT, INFO, ("Open FW image: %s failed\n", CFG_FW_FILENAME));
+        goto error_open;
+    }
+    DBGLOG(INIT, INFO, ("Open FW image: %s done\n", CFG_FW_FILENAME));
+    return WLAN_STATUS_SUCCESS;
+
+error_open:
+    /* restore */
+    set_fs(orgfs);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29))
+    current->fsuid = orgfsuid;
+    current->fsgid = orgfsgid;
+#else
+    cred->fsuid = orgfsuid;
+    cred->fsgid = orgfsgid;
+    #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
+    put_cred(cred);
+    #endif
+#endif
+    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);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29))
+        current->fsuid = orgfsuid;
+        current->fsgid = orgfsgid;
+#else
+        {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
+            struct cred *cred = (struct cred *) get_current_cred();
+#else
+            struct cred *cred = get_task_cred(current);
+#endif
+            cred->fsuid = orgfsuid;
+            cred->fsgid = orgfsgid;
+    #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
+            put_cred(cred);
+    #endif
+        }
+#endif
+        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;
+
+    /* 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);
+    }
+
+    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);
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 12)
+    *pu4Size = filp->f_path.dentry->d_inode->i_size;
+#else
+    *pu4Size = filp->f_dentry->d_inode->i_size;
+#endif
+
+    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
+    )
+{
+    DEBUGFUNC("kalFirmwareImageMapping");
+
+    ASSERT(prGlueInfo);
+    ASSERT(ppvMapFileBuf);
+    ASSERT(pu4FileLength);
+
+    do {
+        /* <1> Open firmware */
+        if (kalFirmwareOpen(prGlueInfo) != WLAN_STATUS_SUCCESS) {
+            break;
+        } else {
+            UINT_32 u4FwSize = 0;
+            PVOID prFwBuffer = NULL;
+            /* <2> Query firmare size */
+            kalFirmwareSize(prGlueInfo, &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);
+                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->func->dev);
+
+        if (i4Ret) {
+            printk (KERN_INFO DRV_NAME"fw %s:request failed %d\n", CFG_FW_FILENAME, i4Ret);
+            break;
+        } else {
+            *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 PUINT_32                    pu4Flags
+    )
+{
+    UINT_32 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;
+    }
+
+    return;
+} /* 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) {
+
+#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 */
+
+    }
+
+    return;
+} /* 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);
+    }
+
+    return;
+}
+
+
+#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 LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+    if (skb->ip_summed == CHECKSUM_HW)
+#else
+    if (skb->ip_summed == CHECKSUM_PARTIAL)
+#endif
+    {
+
+#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 != __constant_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;
+
+    return;
+} /* 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 {
+
+        }
+#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);
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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 = %#lx, prSkb->cb = %#lx\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 = (unsigned char *)pucPacketStart;
+    skb->tail = (unsigned char *) ((UINT_32) (pucPacketStart + u4PacketLen));
+    skb->len = (unsigned int)u4PacketLen;
+
+#if CFG_TCP_IP_CHKSUM_OFFLOAD
+    kalUpdateRxCSUMOffloadParam(skb, aerCSUM);
+#endif
+
+    return rStatus;
+}
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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 = 0x%p, prSkb->cb = 0x%lx\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++;
+
+        }
+
+        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, EVENT, ("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 < 64; i++)
+        {
+            LOG_FUNC("%02x ", prSkb->data[i]);
+
+            if((i+1)%16 ==0)
+            {
+                LOG_FUNC("\n");
+            }
+        }
+
+    LOG_FUNC("\n");
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+        if(!in_interrupt()){
+            netif_rx_ni(prSkb); /* only in non-interrupt context */
+        }
+        else {
+            netif_rx(prSkb);
+        }
+#else
+        netif_rx(prSkb);
+#endif
+
+        wlanReturnPacket(prGlueInfo->prAdapter, NULL);
+    }
+
+    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)
+*
+*/
+/*----------------------------------------------------------------------------*/
+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;
+
+    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(INIT, INFO, ("[wifi] %s netif_carrier_on [ssid:%s " MACSTR "]\n",
+                prGlueInfo->prDevHandler->name,
+                ssid.aucSsid,
+                MAC2STR(arBssid)));
+        } while(0);
+
+        if(prGlueInfo->fgIsRegistered == TRUE) {
+            /* 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, IEEE80211_BAND_2GHZ));
+            }
+            else {
+                prChannel = ieee80211_get_channel(priv_to_wiphy(prGlueInfo), ieee80211_channel_to_frequency(ucChannelNum, IEEE80211_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,
+                        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);
+                }
+            }
+
+            /* CFG80211 Indication */
+            if(eStatus == WLAN_STATUS_MEDIA_CONNECT 
+                    && prGlueInfo->prDevHandler->ieee80211_ptr->sme_state == CFG80211_SME_CONNECTING) {
+                cfg80211_connect_result(prGlueInfo->prDevHandler,
+                        arBssid,
+                        prGlueInfo->aucReqIe,
+                        prGlueInfo->u4ReqIeLength,
+                        prGlueInfo->aucRspIe,
+                        prGlueInfo->u4RspIeLength,
+                        WLAN_STATUS_SUCCESS,
+                        GFP_KERNEL);
+            }
+            else if(eStatus == WLAN_STATUS_ROAM_OUT_FIND_BEST
+                    && prGlueInfo->prDevHandler->ieee80211_ptr->sme_state == CFG80211_SME_CONNECTED) {
+                #if LINUX_VERSION_CODE > KERNEL_VERSION(3, 3, 0)
+
+                               cfg80211_roamed_bss(prGlueInfo->prDevHandler, 
+                        bss,
+                        prGlueInfo->aucReqIe,
+                        prGlueInfo->u4ReqIeLength,
+                        prGlueInfo->aucRspIe,
+                        prGlueInfo->u4RspIeLength,
+                        GFP_KERNEL);
+                #else
+                               struct ieee80211_channel *prChannel = NULL;
+                UINT_8 ucChannelNum = wlanGetChannelNumberByNetwork(prGlueInfo->prAdapter, NETWORK_TYPE_AIS_INDEX);
+
+                if(ucChannelNum <= 14) {
+                    prChannel = ieee80211_get_channel(priv_to_wiphy(prGlueInfo), ieee80211_channel_to_frequency(ucChannelNum, IEEE80211_BAND_2GHZ));
+                }
+                else {
+                    prChannel = ieee80211_get_channel(priv_to_wiphy(prGlueInfo), ieee80211_channel_to_frequency(ucChannelNum, IEEE80211_BAND_5GHZ));
+                }
+
+                cfg80211_roamed(prGlueInfo->prDevHandler, 
+                        prChannel,
+                        arBssid,
+                        prGlueInfo->aucReqIe,
+                        prGlueInfo->u4ReqIeLength,
+                        prGlueInfo->aucRspIe,
+                        prGlueInfo->u4RspIeLength,                        
+                        GFP_KERNEL);
+                               #endif
+               }
+        }
+        break;
+
+    case WLAN_STATUS_MEDIA_DISCONNECT:
+        /* 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 */
+
+#if 1   /* CONSOLE_MESSAGE */
+         DBGLOG(INIT, INFO, ("[wifi] %s netif_carrier_off\n", prGlueInfo->prDevHandler->name));
+#endif
+
+        netif_carrier_off(prGlueInfo->prDevHandler);
+
+        if(prGlueInfo->fgIsRegistered == TRUE
+                && prGlueInfo->prDevHandler->ieee80211_ptr->sme_state == CFG80211_SME_CONNECTED) {
+            /* CFG80211 Indication */
+            cfg80211_disconnected(prGlueInfo->prDevHandler, 0, NULL, 0, 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 */
+        if(prScanRequest != NULL) {
+            cfg80211_scan_done(prScanRequest, FALSE);
+        }
+        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,
+                    REASON_CODE_UNSPECIFIED,
+                    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) [" MACSTR "] F:%lx\n",
+                    pAuth->Request[0].Length,
+                    MAC2STR(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[" MACSTR "] preAuth Flag:%lx\n",
+                        MAC2STR(pPmkid->arCandidateList[0].rBSSID),
+                        pPmkid->arCandidateList[0].fgFlags);
+                }
+                */
+                {
+                 UINT_32  i = 0;
+
+                 P_PARAM_PMKID_CANDIDATE_T prPmkidCand = (P_PARAM_PMKID_CANDIDATE_T)&pPmkid->arCandidateList[0];
+
+                 for (i=0; i<pPmkid->u4NumCandidates; i++) {
+                    wext_indicate_wext_event(prGlueInfo,
+                        IWEVPMKIDCAND,
+                        (unsigned char *)&pPmkid->arCandidateList[i],
+                        pPmkid->u4NumCandidates);
+                    prPmkidCand += sizeof(PARAM_PMKID_CANDIDATE_T);
+                }
+                }
+                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);
+    }
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* @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;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 26)
+    u2QueueIdx = skb_get_queue_mapping(prSkb);
+#endif
+    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);
+    GLUE_DEC_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[ucNetworkType][u2QueueIdx]);
+    prDev = prSkb->dev;
+
+    ASSERT(prDev);
+
+    if(fgIsValidDevice == TRUE) {
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 26)
+        if (netif_subqueue_stopped(prDev, prSkb) &&
+                prGlueInfo->ai4TxPendingFrameNumPerQueue[ucNetworkType][u2QueueIdx] <= CFG_TX_START_NETIF_PER_QUEUE_THRESHOLD) {
+            netif_wake_subqueue(prDev, u2QueueIdx);
+        }
+#else
+        if (prGlueInfo->i4TxPendingFrameNum < CFG_TX_STOP_NETIF_QUEUE_THRESHOLD) {
+            netif_wake_queue(prGlueInfo->prDevHandler);
+        }
+#endif
+    }
+
+
+    dev_kfree_skb((struct sk_buff *) pvPacket);
+
+    DBGLOG(TX, EVENT, ("----- pending frame %d -----\n", prGlueInfo->i4TxPendingFrameNum));
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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);
+
+    return;
+} /* 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
+*
+* @retval TRUE      Success to extract information
+* @retval FALSE     Fail to extract correct information
+*/
+/*----------------------------------------------------------------------------*/
+
+BOOL
+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
+    )
+{
+
+    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(INIT, WARN, ("Invalid Ether packet length: %d\n", 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;
+        //printk ("ip version %x\n", ucIpVersion);
+        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) { /* For Port Control */
+        //DBGLOG(REQ, TRACE, ("Tx 1x\n"));
+        *pfgIs1X = TRUE;
+    }
+    else if (u2EtherTypeLen == ETH_P_PRE_1X) { /* For Pre 1x pkt */
+        //DBGLOG(REQ, TRACE, ("Tx Pre-1x\n"));
+        *pfgIs1X = TRUE;
+    }
+#if CFG_SUPPORT_WAPI
+    else if (u2EtherTypeLen == ETH_WPI_1X) {
+        *pfgIs1X = TRUE;
+    }
+#endif
+    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) {
+                *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;
+    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) {
+        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 BOOL                     fgRead,
+    IN BOOL                     fgWaitResp,
+    IN BOOL                     fgCmd,
+    IN BOOL                     fgIsP2pOid,
+    OUT PUINT_32                pu4QryInfoLen
+    )
+{
+    P_GL_IO_REQ_T prIoReq = NULL;
+    WLAN_STATUS ret = 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 (down_interruptible(&g_halt_sem)) {
+        return WLAN_STATUS_FAILURE;
+    }
+
+
+    if (g_u4HaltFlag) {
+        up(&g_halt_sem);
+        return WLAN_STATUS_ADAPTER_NOT_READY;
+    }
+
+    if(down_interruptible(&prGlueInfo->ioctl_sem)) {
+        up(&g_halt_sem);
+        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->u4Flag);
+
+    /* <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)) {
+    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
+
+    up(&prGlueInfo->ioctl_sem);
+    up(&g_halt_sem);
+    
+
+    
+    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->u4Flag)) {
+            p2pSetMulticastListWorkQueueWrapper(prGlueInfo);
+        }
+#endif
+
+        if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) {
+            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
+         *
+         */
+
+        ret = wait_event_interruptible(prGlueInfo->waitq,
+                (prGlueInfo->u4Flag != 0));
+
+#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->u4Flag)) {
+            p2pSetMulticastListWorkQueueWrapper(prGlueInfo);
+        }
+
+        if (test_and_clear_bit(GLUE_FLAG_FRAME_FILTER_BIT, &prGlueInfo->u4Flag)) {
+            p2pFuncUpdateMgmtFrameRegister(prGlueInfo->prAdapter, prGlueInfo->prP2PInfo->u4OsMgmtFrameFilter);
+        }
+
+        
+#endif
+        if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) {
+            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->u4Flag)) {
+
+            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->u4Flag & GLUE_FLAG_HALT) {
+                /* Should stop now... skip pending interrupt */
+                DBGLOG(INIT, INFO, ("ignore pending interrupt\n"));
+            }
+            else {
+
+                wlanIST(prGlueInfo->prAdapter);
+            }
+        }
+
+        /* transfer ioctl to OID request */
+        #if 0
+        if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) {
+            printk(KERN_INFO DRV_NAME"<2>tx_thread should stop now...\n");
+            break;
+        }
+        #endif
+
+        do {
+            if (test_and_clear_bit(GLUE_FLAG_OID_BIT, &prGlueInfo->u4Flag)) {
+                /* get current prIoReq */
+                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) {
+                        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) {
+            printk(KERN_INFO DRV_NAME"<3>tx_thread should stop now...\n");
+            break;
+        }
+        #endif
+
+        if (test_and_clear_bit(GLUE_FLAG_TXREQ_BIT, &prGlueInfo->u4Flag))
+        {
+
+            /* 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, WARN, ("prSkb == NULL in tx\n"));
+                        continue;
+                    }
+
+                    if(wlanEnqueueTxPacket(prGlueInfo->prAdapter,
+                                (P_NATIVE_PACKET)prSkb) == WLAN_STATUS_RESOURCES) {
+                        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) {
+                    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->u4Flag)) {
+            wlanTimerTimeoutCheck(prGlueInfo->prAdapter);
+        }
+
+    #if CFG_DBG_GPIO_PINS
+        /* TX thread go to sleep */
+        if (!prGlueInfo->u4Flag){
+            mtk_wcn_stp_debug_gpio_assert(IDX_TX_THREAD, DBG_TIE_HIGH);
+        }
+    #endif
+    }
+
+    #if 0
+    if (fgNeedHwAccess == TRUE) {
+        wlanReleasePowerControl(prGlueInfo->prAdapter);
+    }
+    #endif
+
+    /* 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)
+        UINT_32 i;
+        BOOLEAN fgIsReadError = FALSE;
+
+        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;
+            }
+        }
+
+        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;
+        }
+        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);
+
+    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;
+
+    GLUE_SPIN_LOCK_DECLARATION();
+
+    ASSERT(prGlueInfo);
+    ASSERT(prQueueEntry);
+
+    prCmdQue = &prGlueInfo->rCmdQueue;
+
+    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);
+    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);
+
+    init_timer(&(prGlueInfo->tickfn));
+    prGlueInfo->tickfn.function = prTimerHandler;
+    prGlueInfo->tickfn.data = (unsigned long) prGlueInfo;
+}
+
+// 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->u4Flag);
+
+    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
+    )
+{
+    ASSERT(prGlueInfo);
+
+    /* 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 (unsigned long arg)
+{
+
+    P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) arg;
+
+    ASSERT(prGlueInfo);
+
+    /* Notify tx thread  for timeout event */
+    set_bit(GLUE_FLAG_TIMEOUT_BIT, &prGlueInfo->u4Flag);
+    wake_up_interruptible(&prGlueInfo->waitq);
+
+    return;
+}
+
+
+VOID
+kalSetEvent (P_GLUE_INFO_T pr) {
+    set_bit(GLUE_FLAG_TXREQ_BIT, &pr->u4Flag);
+    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);
+
+    return;
+}
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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;
+        pStats->qual.level = 0x100 + cRssi;
+        pStats->qual.updated |= IW_QUAL_LEVEL_UPDATED;
+    }
+
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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);
+    }
+
+    pvIoBuffer = kmalloc(u4Size, 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
+    )
+{
+    if(pvIoBuffer) {
+        kfree(pvIoBuffer);
+
+        pvIoBuffer = (PVOID) NULL;
+        pvIoBufferSize = 0;
+        pvIoBufferUsage = 0;
+    }
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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,
+                              ucMaxChannelNum,
+                              pucNumOfChannel,
+                              paucChannelList);
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief
+*
+* \param[in] prAdapter  Pointer of ADAPTER_T
+*
+* \return none
+*/
+/*----------------------------------------------------------------------------*/
+BOOL
+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;
+}
+
+
+#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,
+    unsigned long long offset,
+    unsigned char* data,
+    unsigned int size)
+{
+    mm_segment_t oldfs;
+    int 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,
+    unsigned long long offset,
+    unsigned char* data,
+    unsigned int size)
+{
+    mm_segment_t oldfs;
+    int 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;
+    UINT_32 u4Flags = 0;
+
+    if(fgDoAppend) {
+        u4Flags = O_APPEND;
+    }
+
+    file = kalFileOpen(pucPath, O_WRONLY | O_CREAT | u4Flags, S_IRWXU);
+    ret = kalFileWrite(file, 0, pucData, u4Size);
+    kalFileClose(file);
+
+    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, IEEE80211_BAND_2GHZ));
+    }
+    else {
+        prChannel = ieee80211_get_channel(wiphy, ieee80211_channel_to_frequency(ucChannelNum, IEEE80211_BAND_5GHZ));
+    }
+
+    if(prChannel != NULL && prGlueInfo->prScanRequest != NULL) {
+        struct cfg80211_bss *bss;
+
+        /* indicate to NL80211 subsystem */
+        bss = cfg80211_inform_bss_frame(wiphy,
+                prChannel,
+                (struct ieee80211_mgmt *)pucBeaconProbeResp,
+                u4FrameLen,
+                i4SignalStrength * 100,
+                GFP_KERNEL);
+
+        if(!bss) {
+            DBGLOG(REQ, WARN, ("cfg80211_inform_bss_frame() returned with NULL\n"));
+        }
+        else {
+            cfg80211_put_bss(bss);
+        }
+    }
+
+    return;
+}
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_p2p.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_p2p.c
new file mode 100755 (executable)
index 0000000..a665e72
--- /dev/null
@@ -0,0 +1,5480 @@
+/*
+** $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 Channle 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 paramters
+ *
+ * 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 continous memory demands
+ * separate kalMemAlloc() into virtually-continous and physically-continous 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 "gl_os.h"
+#include "debug.h"
+#include "wlan_lib.h"
+#include "gl_wext.h"
+#include <linux/poll.h>
+
+#include <linux/kmod.h>
+//#include <net/cfg80211.h>
+#include "gl_p2p_ioctl.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
+/* for cfg80211 - frequency table */
+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),
+};
+
+static struct ieee80211_channel mtk_5ghz_a_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),
+};
+
+/* 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 MT6620_MCS_INFO                                     \
+{                                                           \
+        /* MCS1~7*/                                        \
+        .rx_mask        = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0},\
+        .rx_highest     = 0,                                \
+        .tx_params      = IEEE80211_HT_MCS_TX_DEFINED,      \
+}
+
+#if 0
+/*Bandwidth 20Mhz Only*/
+#define MT6620_HT_CAP                                       \
+{                                                           \
+        .ht_supported   = true,                             \
+        .cap            = IEEE80211_HT_CAP_SM_PS            \
+                        | IEEE80211_HT_CAP_GRN_FLD          \
+                        | IEEE80211_HT_CAP_SGI_20,          \
+        .ampdu_factor   = IEEE80211_HT_MAX_AMPDU_64K,       \
+        .ampdu_density  = IEEE80211_HT_MPDU_DENSITY_NONE,   \
+        .mcs            = MT6620_MCS_INFO,                  \
+}
+#else
+/*Bandwidth 20/40Mhz*/
+#define MT6620_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            = MT6620_MCS_INFO,                  \
+}
+#endif
+
+static struct ieee80211_supported_band mtk_band_2ghz = {
+    .band       = IEEE80211_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     = MT6620_HT_CAP,
+};
+
+static struct ieee80211_supported_band mtk_band_5ghz = {
+    .band       = IEEE80211_BAND_5GHZ,
+    .channels   = mtk_5ghz_a_channels,
+    .n_channels = ARRAY_SIZE(mtk_5ghz_a_channels),
+    .bitrates   = mtk_a_rates,
+    .n_bitrates = mtk_a_rates_size,
+    .ht_cap     = MT6620_HT_CAP,
+};
+
+static const UINT_32 cipher_suites[] = {
+       /* 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
+};
+
+static struct cfg80211_ops mtk_p2p_config_ops = {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) && (CFG_ENABLE_WIFI_DIRECT_CFG_80211 != 0)
+    /* Froyo */
+    .change_virtual_intf    = mtk_p2p_cfg80211_change_iface,      // 1 st
+    .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,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+    .start_ap = mtk_p2p_cfg80211_start_ap,
+    .change_beacon = mtk_p2p_cfg80211_change_beacon,
+    .stop_ap = mtk_p2p_cfg80211_stop_ap,
+#else
+    .add_beacon = mtk_p2p_cfg80211_add_set_beacon,
+    .set_beacon = mtk_p2p_cfg80211_add_set_beacon,
+    .del_beacon = mtk_p2p_cfg80211_stop_ap,
+#endif
+    .set_wiphy_params = mtk_p2p_cfg80211_set_wiphy_params,
+    .del_station = mtk_p2p_cfg80211_del_station,
+    .set_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
+#endif
+};
+
+
+
+/* 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
+};
+
+/*******************************************************************************
+*                                 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)
+{
+    skb->priority = _p2p_cfg80211_classify8021d(skb);
+
+    return au16Wlan1dToQueueIdx[skb->priority];
+}
+
+static struct net_device *g_P2pPrDev;
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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
+    )
+{
+    if (!prDev) {
+        return -ENXIO;
+    }
+
+    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
+    )
+{
+
+
+    return;
+} /* end of p2pUninit() */
+
+
+
+
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
+static const struct net_device_ops p2p_netdev_ops = {
+    .ndo_open               = p2pOpen,
+    .ndo_stop               = p2pStop,
+    .ndo_set_mac_address    = p2pSetMACAddress,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+    .ndo_set_rx_mode = p2pSetMulticastList,
+#else
+    .ndo_set_multicast_list = p2pSetMulticastList,
+#endif
+    .ndo_get_stats          = p2pGetStats,
+    .ndo_do_ioctl           = p2pDoIOCTL,
+    .ndo_start_xmit         = p2pHardStartXmit,
+    .ndo_select_queue =  p2pSelectQueue,
+    .ndo_init          = p2pInit,
+    .ndo_uninit         = p2pUninit,
+};
+
+
+#endif
+
+
+/*******************************************************************************
+*                              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;
+
+    ASSERT(prGlueInfo);
+
+    prAdapter = prGlueInfo->prAdapter;
+    prWifiVar = &(prAdapter->rWifiVar);
+
+    ASSERT(prAdapter);
+    ASSERT(prWifiVar);
+
+    do {
+        if (prGlueInfo == NULL) {
+            break;
+        }
+
+        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 */
+        kalMemZero(prGlueInfo->prP2PInfo, sizeof(GL_P2P_INFO_T));
+        kalMemZero(prAdapter->prP2pInfo, sizeof(P2P_INFO_T));
+        kalMemZero(prWifiVar->prP2PConnSettings, sizeof(P2P_CONNECTION_SETTINGS_T));
+        kalMemZero(prWifiVar->prP2pFsmInfo, sizeof(P2P_FSM_INFO_T));
+        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;
+    }
+    else {
+
+        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
+    )
+{
+
+    ASSERT(prGlueInfo);
+    ASSERT(prGlueInfo->prAdapter);
+
+    /* 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;
+    }
+
+}
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief Enable Channel  for cfg80211 for Wi-Fi Direct based on current country code
+*
+* \param[in] prGlueInfo      Pointer to glue info
+*
+* \return   TRUE
+*           FALSE
+*/
+/*----------------------------------------------------------------------------*/
+VOID
+p2pEnableChannel(
+    PUINT_8 pucChIdx,
+    UINT_8 ucChannelNum,
+    struct ieee80211_channel *mtk_channels,
+    UINT_8 mtk_channel_sz
+)
+{
+    UINT_8 ucCurChIdx = *pucChIdx;
+
+    while(TRUE) {
+        (*pucChIdx)++;
+        (*pucChIdx) %= mtk_channel_sz;
+
+        if(ucChannelNum == mtk_channels[*pucChIdx].hw_value) {
+            mtk_channels[*pucChIdx].flags &= ~IEEE80211_CHAN_DISABLED;
+            break;
+        }
+
+        if(*pucChIdx == ucCurChIdx) {
+            printk(KERN_ALERT DRV_NAME "Orphan channel [%d]\n", ucChannelNum);
+            break;
+        }
+    }
+}
+
+
+BOOLEAN
+p2pNetRegister(
+    P_GLUE_INFO_T prGlueInfo,
+    BOOLEAN fgIsRtnlLockAcquired
+    )
+{
+    BOOLEAN fgDoRegister = FALSE;
+    BOOLEAN fgRollbackRtnlLock = FALSE;
+    BOOLEAN ret;
+
+    GLUE_SPIN_LOCK_DECLARATION();
+
+    ASSERT(prGlueInfo);
+    ASSERT(prGlueInfo->prAdapter);
+
+
+    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;
+    }
+
+    if(fgIsRtnlLockAcquired && rtnl_is_locked()) {
+        fgRollbackRtnlLock = TRUE;
+        rtnl_unlock();
+    }
+
+    /* Here are functions which need rtnl_lock */
+    wiphy_register(prGlueInfo->prP2PInfo->wdev.wiphy);
+
+    /* 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) {
+        printk(KERN_ALERT DRV_NAME "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;
+    }
+
+    if(fgRollbackRtnlLock) {
+        rtnl_lock();
+    }
+
+    return ret;
+}
+
+BOOLEAN
+p2pNetUnregister(
+    P_GLUE_INFO_T prGlueInfo,
+    BOOLEAN fgIsRtnlLockAcquired
+    )
+{
+    BOOLEAN fgDoUnregister = FALSE;
+    BOOLEAN fgRollbackRtnlLock = FALSE;
+
+    GLUE_SPIN_LOCK_DECLARATION();
+
+    ASSERT(prGlueInfo);
+    ASSERT(prGlueInfo->prAdapter);
+
+    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);
+
+    if(fgIsRtnlLockAcquired && rtnl_is_locked()) {
+        fgRollbackRtnlLock = TRUE;
+        rtnl_unlock();
+    }
+    /* Here are functions which need rtnl_lock */
+
+    unregister_netdev(prGlueInfo->prP2PInfo->prDevHandler);
+
+    wiphy_unregister(prGlueInfo->prP2PInfo->wdev.wiphy);
+
+    if(fgRollbackRtnlLock) {
+        rtnl_lock();
+    }
+
+    prGlueInfo->prAdapter->rP2PNetRegState = ENUM_NET_REG_STATE_UNREGISTERED;
+
+    return TRUE;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief Update Channel table for cfg80211 for Wi-Fi Direct based on current country code
+*
+* \param[in] prGlueInfo      Pointer to glue info
+*
+* \return   TRUE
+*           FALSE
+*/
+/*----------------------------------------------------------------------------*/
+VOID
+p2pUpdateChannelTableByDomain(
+    P_GLUE_INFO_T prGlueInfo
+    )
+{
+    UINT_8 i, uc2gChIdx, uc5gChIdx;
+    UINT_8 ucMaxChannelNum = ARRAY_SIZE(mtk_2ghz_channels) + ARRAY_SIZE(mtk_5ghz_a_channels);
+    UINT_8 ucNumOfChannel = ucMaxChannelNum;
+    RF_CHANNEL_INFO_T aucChannelList[ucMaxChannelNum];
+
+    uc2gChIdx = uc5gChIdx = 0;
+
+    // 1. Disable all channel
+    for(i = 0; i < ARRAY_SIZE(mtk_2ghz_channels); i++) {
+        mtk_2ghz_channels[i].flags |= IEEE80211_CHAN_DISABLED;
+    }
+    for(i = 0; i < ARRAY_SIZE(mtk_5ghz_a_channels); i++) {
+        mtk_5ghz_a_channels[i].flags |= IEEE80211_CHAN_DISABLED;
+    }
+
+    // 2. Get current domain channel list
+    rlmDomainGetChnlList(prGlueInfo->prAdapter, BAND_NULL, ucMaxChannelNum, &ucNumOfChannel, aucChannelList);
+
+    // 3. Enable specific channel based on domain channel list
+    for(i = 0; i < ucNumOfChannel; i++) {
+        switch(aucChannelList[i].eBand) {
+            case BAND_2G4:
+                p2pEnableChannel(&uc2gChIdx, aucChannelList[i].ucChannelNum, mtk_2ghz_channels, ARRAY_SIZE(mtk_2ghz_channels));
+                break;
+
+            case BAND_5G:
+                p2pEnableChannel(&uc5gChIdx, aucChannelList[i].ucChannelNum, mtk_5ghz_a_channels, ARRAY_SIZE(mtk_5ghz_a_channels));
+                break;
+
+            default:
+                printk(KERN_ALERT DRV_NAME "Unknow band.\n");
+                break;
+
+        }
+    }
+
+}
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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;
+#if CFG_ENABLE_WIFI_DIRECT_CFG_80211
+    struct device *prDev;
+#endif
+
+    ASSERT(prGlueInfo);
+
+    prAdapter = prGlueInfo->prAdapter;
+    ASSERT(prAdapter);
+
+    prHif = &prGlueInfo->rHifInfo;
+    ASSERT(prHif);
+
+    printk("glRegisterP2P\n");
+
+    /*0. allocate p2pinfo */
+    if(!p2PAllocInfo(prGlueInfo)) {
+        printk(KERN_ALERT DRV_NAME "Allocate memory for p2p FAILED\n");
+        ASSERT(0);
+        return FALSE;
+    }
+#if CFG_ENABLE_WIFI_DIRECT_CFG_80211
+    /* 1. allocate WIPHY */
+    prGlueInfo->prP2PInfo->wdev.wiphy = wiphy_new(&mtk_p2p_config_ops, sizeof(P_GLUE_INFO_T));
+    if (!prGlueInfo->prP2PInfo->wdev.wiphy) {
+        printk(KERN_ALERT DRV_NAME "unable to allocate wiphy for p2p\n");
+
+        goto err_alloc_wiphy;
+    }
+
+    /* 1.1 fill wiphy parameters */
+#if MTK_WCN_HIF_SDIO
+    mtk_wcn_hif_sdio_get_dev(prHif->cltCtx, &prDev);
+    if(!prDev) {
+        printk(KERN_ALERT DRV_NAME "unable to get struct dev for p2p\n");
+    }
+#else
+    prDev = &(prHif->func->dev);
+#endif
+    set_wiphy_dev(prGlueInfo->prP2PInfo->wdev.wiphy, prDev);
+
+    prGlueInfo->prP2PInfo->wdev.wiphy->interface_modes = BIT(NL80211_IFTYPE_AP)
+                                                       | BIT(NL80211_IFTYPE_P2P_CLIENT)
+                                                       | BIT(NL80211_IFTYPE_P2P_GO)
+                                                       | BIT(NL80211_IFTYPE_STATION);
+
+    p2pUpdateChannelTableByDomain(prGlueInfo);
+    prGlueInfo->prP2PInfo->wdev.wiphy->bands[IEEE80211_BAND_2GHZ] = &mtk_band_2ghz;
+    if(prAdapter->fgEnable5GBand) {
+        prGlueInfo->prP2PInfo->wdev.wiphy->bands[IEEE80211_BAND_5GHZ] = &mtk_band_5ghz;
+    }
+
+    prGlueInfo->prP2PInfo->wdev.wiphy->mgmt_stypes = mtk_cfg80211_default_mgmt_stypes;
+    prGlueInfo->prP2PInfo->wdev.wiphy->max_remain_on_channel_duration = 5000;
+    prGlueInfo->prP2PInfo->wdev.wiphy->n_cipher_suites = 5;
+       prGlueInfo->prP2PInfo->wdev.wiphy->cipher_suites = (const u32*)cipher_suites;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
+       prGlueInfo->prP2PInfo->wdev.wiphy->flags = WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
+#else
+       prGlueInfo->prP2PInfo->wdev.wiphy->flags = WIPHY_FLAG_CUSTOM_REGULATORY;
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
+    prGlueInfo->prP2PInfo->wdev.wiphy->max_scan_ssids = MAX_SCAN_LIST_NUM;
+    prGlueInfo->prP2PInfo->wdev.wiphy->max_scan_ie_len = MAX_SCAN_IE_LEN;
+    prGlueInfo->prP2PInfo->wdev.wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+#endif
+
+#if 0
+    /* 2. Register WIPHY */
+    if(wiphy_register(prGlueInfo->prP2PInfo->wdev.wiphy) < 0) {
+        printk(KERN_ALERT DRV_NAME "Couldn't register wiphy device for p2p\n");
+
+        goto err_reg_wiphy;
+    }
+#endif
+
+    /* 2.1 set priv as pointer to glue structure */
+    *((P_GLUE_INFO_T *) wiphy_priv(prGlueInfo->prP2PInfo->wdev.wiphy)) = prGlueInfo;
+
+    /* 2.2 wdev initialization */
+    if(fgIsApMode) {
+        prGlueInfo->prP2PInfo->wdev.iftype = NL80211_IFTYPE_AP;
+    } else {
+        prGlueInfo->prP2PInfo->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT;
+    }
+
+#endif /* CFG_ENABLE_WIFI_DIRECT_CFG_80211 */
+
+    /* 3. allocate netdev */
+    prGlueInfo->prP2PInfo->prDevHandler = alloc_netdev_mq(sizeof(P_GLUE_INFO_T), prDevName, ether_setup, CFG_MAX_TXQ_NUM);
+    if (!prGlueInfo->prP2PInfo->prDevHandler) {
+        printk(KERN_ALERT DRV_NAME "unable to allocate netdevice for p2p\n");
+
+        printk("unable to allocate netdevice for p2p\n");
+
+        goto err_alloc_netdev;
+    }
+
+    /* 4. setup netdev */
+    /* 4.1 Point to shared glue structure */
+    *((P_GLUE_INFO_T *) netdev_priv(prGlueInfo->prP2PInfo->prDevHandler)) = 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 */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
+    prGlueInfo->prP2PInfo->prDevHandler->netdev_ops           = &p2p_netdev_ops;
+#else
+    prGlueInfo->prP2PInfo->prDevHandler->open                 = p2pOpen;
+    prGlueInfo->prP2PInfo->prDevHandler->stop                 = p2pStop;
+    prGlueInfo->prP2PInfo->prDevHandler->get_stats            = p2pGetStats;
+    prGlueInfo->prP2PInfo->prDevHandler->set_multicast_list   = p2pSetMulticastList;
+    prGlueInfo->prP2PInfo->prDevHandler->hard_start_xmit      = p2pHardStartXmit;
+    prGlueInfo->prP2PInfo->prDevHandler->do_ioctl             = p2pDoIOCTL;
+    prGlueInfo->prP2PInfo->prDevHandler->set_mac_address      = p2pSetMACAddress;
+#endif
+//    prGlueInfo->prP2PInfo->prDevHandler->wireless_handlers    = &mtk_p2p_wext_handler_def;
+
+
+#if (MTK_WCN_HIF_SDIO == 0)
+    SET_NETDEV_DEV(prGlueInfo->prP2PInfo->prDevHandler, &(prHif->func->dev));
+#endif
+
+
+#if CFG_ENABLE_WIFI_DIRECT_CFG_80211
+    prGlueInfo->prP2PInfo->prDevHandler->ieee80211_ptr        = &(prGlueInfo->prP2PInfo->wdev);
+    prGlueInfo->prP2PInfo->wdev.netdev                        = prGlueInfo->prP2PInfo->prDevHandler;
+#endif
+
+#if CFG_TCP_IP_CHKSUM_OFFLOAD
+    prGlueInfo->prP2PInfo->prDevHandler->features = NETIF_F_IP_CSUM;
+#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */
+
+#if 0
+    /* 7. net device initialize */
+    netif_carrier_off(prGlueInfo->prP2PInfo->prDevHandler);
+    netif_tx_stop_all_queues(prGlueInfo->prP2PInfo->prDevHandler);
+
+    /* 8. register for net device */
+    if (register_netdev(prGlueInfo->prP2PInfo->prDevHandler) < 0) {
+        printk(KERN_ALERT DRV_NAME "unable to register netdevice for p2p\n");
+
+        goto err_reg_netdev;
+    }
+#endif
+
+    /* 8. set p2p net device register state */
+    prGlueInfo->prAdapter->rP2PNetRegState = ENUM_NET_REG_STATE_UNREGISTERED;
+
+    /* 9. setup running mode*/
+    prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->fgIsApMode = fgIsApMode;
+
+    /* 10. 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;
+#if 0
+err_reg_netdev:
+    free_netdev(prGlueInfo->prP2PInfo->prDevHandler);
+#endif
+err_alloc_netdev:
+#if CFG_ENABLE_WIFI_DIRECT_CFG_80211
+//    wiphy_unregister(prGlueInfo->prP2PInfo->wdev.wiphy);
+
+//err_reg_wiphy:
+    wiphy_free(prGlueInfo->prP2PInfo->wdev.wiphy);
+    prGlueInfo->prP2PInfo->wdev.wiphy = NULL;
+
+err_alloc_wiphy:
+#endif
+
+    return FALSE;
+} /* 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);
+
+    p2pFsmUninit(prGlueInfo->prAdapter);
+
+    nicDeactivateNetwork(prGlueInfo->prAdapter, NETWORK_TYPE_P2P_INDEX);
+
+#if 0
+    /* Release command, mgmt and security frame belong to P2P network in
+         *   prGlueInfo->prCmdQue
+         *   prAdapter->rPendingCmdQueue
+         *   prAdapter->rTxCtrl.rTxMgmtTxingQueue
+         *  To ensure there is no pending CmdDone/TxDone handler to be executed after p2p module is removed.
+         */
+
+    /* Clear CmdQue*/
+    kalClearMgmtFramesByNetType(prGlueInfo, NETWORK_TYPE_P2P_INDEX);
+    kalClearSecurityFramesByNetType(prGlueInfo, NETWORK_TYPE_P2P_INDEX);
+    /* Clear PendingCmdQue*/
+    wlanReleasePendingCMDbyNetwork(prGlueInfo->prAdapter, NETWORK_TYPE_P2P_INDEX);
+    /* Clear PendingTxMsdu */
+    nicFreePendingTxMsduInfoByNetwork(prGlueInfo->prAdapter, NETWORK_TYPE_P2P_INDEX);
+#endif
+
+#if 0
+    /* prepare for removal */
+    if(netif_carrier_ok(prGlueInfo->prP2PInfo->prDevHandler)) {
+        netif_carrier_off(prGlueInfo->prP2PInfo->prDevHandler);
+    }
+
+    netif_tx_stop_all_queues(prGlueInfo->prP2PInfo->prDevHandler);
+
+    /* netdevice unregistration & free */
+    unregister_netdev(prGlueInfo->prP2PInfo->prDevHandler);
+#endif
+    free_netdev(prGlueInfo->prP2PInfo->prDevHandler);
+    prGlueInfo->prP2PInfo->prDevHandler = NULL;
+
+#if CFG_ENABLE_WIFI_DIRECT_CFG_80211
+#if 0
+    wiphy_unregister(prGlueInfo->prP2PInfo->wdev.wiphy);
+#endif
+    wiphy_free(prGlueInfo->prP2PInfo->wdev.wiphy);
+    prGlueInfo->prP2PInfo->wdev.wiphy = NULL;
+#endif
+
+    /* Free p2p memory */
+#if 1
+    if(!p2PFreeInfo(prGlueInfo)) {
+        printk(KERN_ALERT DRV_NAME "Free memory for p2p FAILED\n");
+        ASSERT(0);
+        return FALSE;
+    }
+#endif
+    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
+        printk(KERN_ALERT DRV_NAME "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_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, TRUE);
+               }
+       
+#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 0 // frog temp fix
+    //@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) {
+        printk(KERN_WARNING DRV_NAME" 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;
+    /* wake up main thread */
+    wake_up_interruptible(&prGlueInfo->waitq);
+
+} /* p2pSetMulticastList */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+ * \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) {
+        printk(KERN_WARNING DRV_NAME" 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) ||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+                (netdev_mc_count(prDev) > MAX_NUM_GROUP_ADDR)) {
+#else
+                (prDev->mc_count > MAX_NUM_GROUP_ADDR)) {
+#endif
+            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 */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+        struct netdev_hw_addr *ha;
+#else
+        struct dev_mc_list *prMcList;
+#endif
+        UINT_32 i = 0;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+                netdev_for_each_mc_addr(ha, prDev) {
+                    if(i < MAX_NUM_GROUP_ADDR) {
+                        COPY_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucMCAddrList[i]), ha->addr);
+                        i++;
+                    }
+                }
+#else
+                for (i = 0, prMcList = prDev->mc_list;
+                     (prMcList) && (i < prDev->mc_count) && (i < MAX_NUM_GROUP_ADDR);
+                     i++, prMcList = prMcList->next) {
+                    COPY_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucMCAddrList[i]), prMcList->dmi_addr);
+                }
+#endif
+
+                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);
+
+    }
+
+    return;
+} /* end of p2pSetMulticastList() */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+ * * \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));
+
+    if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) {
+        printk(KERN_INFO DRV_NAME"GLUE_FLAG_HALT skip tx\n");
+        dev_kfree_skb(prSkb);
+        return NETDEV_TX_OK;
+    }
+
+    // mark as P2P packets
+    GLUE_SET_PKT_FLAG_P2P(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) {
+            printk(KERN_INFO DRV_NAME"Incorrect queue index, skip this frame\n");
+            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) {
+            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++;
+
+    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 WLAN_STATUS_SUCCESS The IOCTL command is executed successfully.
+ * \retval OTHER 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);
+
+    prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+
+    if (prGlueInfo->u4ReadyFlag == 0) {
+        // adapter not ready yet
+        return -EINVAL;
+    }
+
+    // fill rIwReqInfo
+    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)) {
+            printk(KERN_INFO "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
+    default:
+        ret = -ENOTTY;
+    }
+
+    return ret;
+} /* end of p2pDoIOCTL() */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+ * \brief To report the private supported IOCTLs table to user space.
+ *
+ * \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 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 = 0;
+
+    ASSERT(prDev);
+
+    u2BufferSize = prData->length;
+
+    /* update our private table size */
+    prData->length = (__u16)sizeof(rP2PIwPrivTable)/sizeof(struct iw_priv_args);
+
+    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;
+        }
+        else {
+            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;
+            prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE);
+
+            if (!prExtraBuf) {
+                ret = -ENOMEM;
+                break;
+            }
+
+            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;
+        prIWEncExt = (struct iw_encode_ext *) prExtraBuf;
+
+        if (GLUE_CHK_PR3(prDev, prEnc, prExtraBuf) == TRUE) {
+            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 = ((UINT_32)&(((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;
+                }
+            }
+        }
+        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 {
+            printk(KERN_DEBUG "%s(): unsupported power management mode value = %d.\n",
+                __FUNCTION__,
+                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;
+
+    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 = 8 + sizeof("p2p_cap=");
+
+            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 = 12 + sizeof("p2p_dev_type=");
+
+            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=");
+
+            snprintf(data, iwe.u.data.length, "p2p_grp_bssid="MACSTR"%c",
+                MAC2STR(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];
+
+    printk("set parameter, u4SubCmd=%d idx=%d value=%lu\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)) {
+            printk(KERN_INFO DRV_NAME"extra buffer is valid\n");
+        }
+        else {
+            printk(KERN_INFO DRV_NAME"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)) {
+//                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)) {
+//                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)) {
+            printk(KERN_INFO DRV_NAME"extra buffer is valid\n");
+        }
+        else {
+            printk(KERN_INFO DRV_NAME"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)) {
+            printk(KERN_INFO DRV_NAME"extra buffer is valid\n");
+        }
+        else {
+            printk(KERN_INFO DRV_NAME"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) {
+        printk(KERN_INFO DRV_NAME "%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))) {
+            printk(KERN_NOTICE "%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))) {
+                printk(KERN_NOTICE "%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))) {
+                printk(KERN_NOTICE "%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;
+
+            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))) {
+                printk(KERN_NOTICE "%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))) {
+                    printk(KERN_NOTICE "%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))) {
+                    printk(KERN_NOTICE "%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))) {
+            printk(KERN_NOTICE "%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))) {
+            printk(KERN_NOTICE "%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))) {
+                printk(KERN_NOTICE "%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))) {
+                printk(KERN_NOTICE "%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;
+    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;
+    }
+    else {
+        prP2PReq->outBufferLength = u4QueryInfoLen;
+
+        if(copy_to_user(wrqu->data.pointer,
+                    &(prGlueInfo->prP2PInfo->aucOidBuf[0]),
+                    u4QueryInfoLen + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) {
+            printk(KERN_NOTICE "%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;
+    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;
+    }
+    else {
+        prP2PReq->outBufferLength = u4QueryInfoLen;
+
+        if(copy_to_user(wrqu->data.pointer,
+                    &(prGlueInfo->prP2PInfo->aucOidBuf[0]),
+                    u4QueryInfoLen + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) {
+            printk(KERN_NOTICE "%s() copy_to_user() fail\n", __func__);
+            return -EIO;
+        }
+        else {
+            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;
+    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);
+
+    printk("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;
+    }
+    else {
+        prP2PReq->outBufferLength = u4QueryInfoLen;
+
+        if(copy_to_user(wrqu->data.pointer,
+                    prP2PReq->aucBuffer,
+                    u4QueryInfoLen + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) {
+            printk(KERN_NOTICE "%s() copy_to_user() fail\n", __func__);
+            return -EIO;
+        }
+        else {
+            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_STRUC_T prNoaParam = (P_PARAM_CUSTOM_NOA_PARAM_STRUC_T)extra;
+    P_GLUE_INFO_T               prGlueInfo = NULL;
+
+    ASSERT(prDev);
+
+    prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+    ASSERT(prGlueInfo);
+
+    printk("mtk_p2p_wext_set_noa_param\n");
+
+    rStatus = kalIoctl(prGlueInfo,
+            wlanoidSetNoaParam,
+            prNoaParam, //prP2PReq->aucBuffer,
+            sizeof(PARAM_CUSTOM_NOA_PARAM_STRUC_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_STRUC_T prOppPsParam = (P_PARAM_CUSTOM_OPPPS_PARAM_STRUC_T)extra;
+    P_GLUE_INFO_T               prGlueInfo = NULL;
+
+    ASSERT(prDev);
+
+    prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+    ASSERT(prGlueInfo);
+
+     printk("mtk_p2p_wext_set_oppps_param\n");
+
+   rStatus = kalIoctl(prGlueInfo,
+            wlanoidSetOppPsParam,
+            prOppPsParam, //prP2PReq->aucBuffer,
+            sizeof(PARAM_CUSTOM_OPPPS_PARAM_STRUC_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/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_p2p_cfg80211.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_p2p_cfg80211.c
new file mode 100755 (executable)
index 0000000..83ce96f
--- /dev/null
@@ -0,0 +1,2305 @@
+/*
+** $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 $
+** 
+** 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 <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+#include <linux/ieee80211.h>
+#include <net/cfg80211.h>
+
+#include "precomp.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
+********************************************************************************
+*/
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
+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) {
+        memcpy(rKey.arBSSID, mac_addr, ETH_ALEN);
+        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 =  ((UINT_32)&(((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));
+
+    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 -EINVAL;
+}
+
+int mtk_p2p_cfg80211_get_station(
+    struct wiphy *wiphy,
+    struct net_device *ndev,
+    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,
+                                                mac,
+                                                &rP2pStaInfo);
+
+        /* Inactive time. */
+        sinfo->filled |= STATION_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 net_device *ndev,
+    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---------] */
+
+
+    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;
+            break;
+        }
+
+        DBGLOG(P2P, TRACE, ("Generating scan request message.\n"));
+
+        prMsgScanRequest->rMsgHdr.eMsgId = MID_MNY_P2P_DEVICE_DISCOVERY;
+
+
+
+        DBGLOG(P2P, TRACE, ("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 IEEE80211_BAND_2GHZ:
+                prRfChannelInfo->eBand = BAND_2G4;
+                break;
+            case IEEE80211_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 (request->n_ssids) {
+            ASSERT(prSsidStruct == &(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"));
+
+
+        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,
+    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,
+    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;
+
+    ASSERT(wiphy);
+
+    prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy));
+
+    // not implemented yet
+    // TODO: for JB.
+
+    return -EINVAL;
+}
+
+//&&&&&&&&&&&&&&&&&&&&&&&&&& Add for ICS Wi-Fi Direct Support. &&&&&&&&&&&&&&&&&&&&&&&
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+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;
+
+    do {
+        if ((wiphy == NULL) || (settings == NULL)) {
+            break;
+        }
+
+        DBGLOG(P2P, TRACE, ("mtk_p2p_cfg80211_start_ap.\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) + 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)((UINT_32)pucBuffer + (UINT_32)settings->beacon.head_len);
+        }
+        else {
+            prP2pBcnUpdateMsg->u4BcnHdrLen = 0;
+
+            prP2pBcnUpdateMsg->pucBcnHdr = NULL;
+        }
+
+        if (settings->beacon.tail_len != 0) {
+            UINT_8 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;
+
+    } 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)((UINT_32)pucBuffer + (UINT_32)info->head_len);
+        }
+        else {
+            prP2pBcnUpdateMsg->u4BcnHdrLen = 0;
+
+            prP2pBcnUpdateMsg->pucBcnHdr = NULL;
+        }
+
+        if (info->tail_len != 0) {
+            UINT_8 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 */
+
+#else
+int
+mtk_p2p_cfg80211_add_set_beacon (
+    struct wiphy *wiphy,
+    struct net_device *dev,
+    struct beacon_parameters *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;
+    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;
+
+    do {
+        if ((wiphy == NULL) || (info == NULL)) {
+            break;
+        }
+
+        DBGLOG(P2P, TRACE, ("mtk_p2p_cfg80211_add_set_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)((UINT_32)pucBuffer + (UINT_32)info->head_len);
+        }
+        else {
+            prP2pBcnUpdateMsg->u4BcnHdrLen = 0;
+
+            prP2pBcnUpdateMsg->pucBcnHdr = NULL;
+        }
+
+        if (info->tail_len != 0) {
+            UINT_8 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);
+
+
+        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 = FALSE;
+
+        prP2pStartAPMsg->u4BcnInterval = info->interval;
+
+        prP2pStartAPMsg->u4DtimPeriod = info->dtim_period;
+
+        /* Copy NO SSID. */
+        prP2pStartAPMsg->ucHiddenSsidType = ENUM_HIDDEN_SSID_NONE;
+
+#if 0
+        if (info->head_len > OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem)) {
+            P_WLAN_BEACON_FRAME_T prWlanBcnFrame = info->head;
+
+            prSsidIE = (P_IE_HDR_T)p2pFuncGetSpecIE(prGlueInfo->prAdapter,
+                                    (PUINT_8)prWlanBcnFrame->aucInfoElem,
+                                    (info->head_len - OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem)),
+                                    ELEM_ID_SSID,
+                                    NULL);
+
+            kalMemCopy(prP2pStartAPMsg->aucSsid, SSID_IE(prSsidIE)->aucSSID, IE_LEN(prSsidIE));
+
+        }
+#endif
+
+        mboxSendMsg(prGlueInfo->prAdapter,
+                            MBOX_ID_0,
+                            (P_MSG_HDR_T)prP2pStartAPMsg,
+                            MSG_SEND_METHOD_BUF);
+
+        i4Rslt = 0;
+
+    } while (FALSE);
+
+    return i4Rslt;
+}
+/* mtk_p2p_cfg80211_add_set_beacon */
+#endif
+
+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;
+    } 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
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)
+    , void *cookie
+#endif
+    )
+{
+    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
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)
+    , void *cookie
+#endif
+    )
+{
+    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 net_device *dev,
+    struct ieee80211_channel *chan,
+    enum nl80211_channel_type channel_type,
+    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) ||
+                (dev == 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,
+                                                    channel_type,
+                                                    &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 net_device *dev,
+    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) || (dev == 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 net_device *dev,
+    struct ieee80211_channel *chan, bool offchan,
+    enum nl80211_channel_type channel_type,
+    bool channel_type_valid, unsigned int wait,
+    const u8 *buf,
+    size_t len,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+    bool no_cck,
+    bool dont_wait_for_ack,
+#endif
+    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;
+    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) ||
+                (buf == NULL) ||
+                (len == 0) ||
+                (dev == NULL) ||
+                (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;
+        }
+
+        prMsgTxReq->fgNoneCckRate = FALSE;
+        prMsgTxReq->fgIsWaitRsp = TRUE;
+
+        prMgmtFrame = cnmMgtPktAlloc(prGlueInfo->prAdapter, (UINT_32)(len + MAC_TX_RESERVED_FIELD));
+
+        if ((prMsgTxReq->prMgmtMsduInfo = prMgmtFrame) == NULL) {
+            ASSERT(FALSE);
+            i4Rslt = -ENOMEM;
+            break;
+        }
+
+        prMsgTxReq->u8Cookie = *cookie;
+        prMsgTxReq->rMsgHdr.eMsgId = MID_MNY_P2P_MGMT_TX;
+
+        pucFrameBuf = (PUINT_8)((UINT_32)prMgmtFrame->prPacket + MAC_TX_RESERVED_FIELD);
+
+        kalMemCopy(pucFrameBuf, buf, len);
+
+        prMgmtFrame->u2FrameLength = 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,
+    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;
+
+
+    do {
+        if ((wiphy == NULL) ||
+                    (dev == NULL)) {
+            break;
+        }
+
+        if (mac == NULL) {
+            mac = aucBcMac;
+        }
+
+        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, 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, TRACE, ("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;
+            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_UNBUF);
+
+        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,
+    IN struct net_device *dev,
+    IN struct ieee80211_channel *chan,
+    IN enum nl80211_channel_type channel_type)
+{
+    INT_32 i4Rslt = -EINVAL;
+    P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)NULL;
+    RF_CHANNEL_INFO_T rRfChnlInfo;
+
+    do {
+        if ((wiphy == NULL) ||
+                (dev == NULL) ||
+                (chan == 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(chan,
+                                        channel_type,
+                                        &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,
+    IN struct net_device *dev,
+    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) ||
+                (dev == 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;
+
+        /* 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);
+
+
+    return;
+} /* 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 IEEE80211_BAND_2GHZ:
+                prRfChnlInfo->eBand = BAND_2G4;
+                break;
+            case IEEE80211_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 void *data,
+    IN int len
+    )
+{
+    P_GLUE_INFO_T prGlueInfo = NULL;
+    P_NL80211_DRIVER_TEST_PARAMS prParams = (P_NL80211_DRIVER_TEST_PARAMS)NULL;
+    BOOLEAN fgIsValid = FALSE;
+
+    ASSERT(wiphy);
+
+    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;
+
+    if(prParams->index >> 24 == 0x01) { 
+        /* New version */
+        prParams->index = prParams->index & ~ BITS(24,31);
+    }
+    else {  
+        /* Old version*/
+        mtk_p2p_cfg80211_testmode_p2p_sigma_pre_cmd(wiphy, data, len); 
+               fgIsValid = TRUE;
+        return fgIsValid;
+    }
+
+    /* Clear the version byte */
+    prParams->index = prParams->index & ~ BITS(24,31);
+
+       if(prParams){
+               switch(prParams->index){
+                   case 1: /* P2P Simga */
+                           if(mtk_p2p_cfg80211_testmode_p2p_sigma_cmd(wiphy, data, len))
+                                       fgIsValid = TRUE;
+                           break;
+#if CFG_SUPPORT_WFD 
+                       case 2: /* WFD */
+                               if(mtk_p2p_cfg80211_testmode_wfd_update_cmd(wiphy, data, len))
+                                       fgIsValid= TRUE;
+                           break;
+#endif
+            case 3: /* Hotspot Client Management */
+                if(mtk_p2p_cfg80211_testmode_hotspot_block_list_cmd(wiphy, data, len))
+                                       fgIsValid = TRUE;
+                break;
+                       default:
+                               fgIsValid = TRUE;
+                           break;
+               }
+       }
+
+       return fgIsValid;
+
+}
+
+
+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=%lu\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;
+
+    index = (INT_32)prParams->idx;
+    value = (INT_32)prParams->value;
+
+       DBGLOG(P2P, TRACE, ("NL80211_ATTR_TESTDATA, idx=%lu value=%lu\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;
+      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;
+
+    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"));
+
+#if 1
+
+    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 "MACSTR" \n", MAC2STR(prParams->WfdCoupleSinkAddress)));
+    DBGLOG(P2P, INFO,("WFD Associated BSSID "MACSTR" \n", MAC2STR(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 "MACSTR" \n", MAC2STR(prParams->aucWfdPrimarySinkMac)));
+    DBGLOG(P2P, INFO,("WFD Secondary Sink Addr "MACSTR" \n", MAC2STR(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];
+
+#endif
+
+    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_list_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;
+    int fgIsValid = 0;
+
+    ASSERT(wiphy);
+
+    prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy));
+
+    if(data && len)
+        prParams = (P_NL80211_DRIVER_hotspot_block_PARAMS)data;
+
+    DBGLOG(P2P, TRACE, ("mtk_p2p_cfg80211_testmode_hotspot_block_list_cmd\n"));
+
+    fgIsValid = kalP2PSetBlackList(prGlueInfo, prParams->aucBssid, prParams->ucblocked);
+    return fgIsValid;
+
+}
+
+#endif
+
+
+#endif // LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
+
+#endif // CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_WIFI_DIRECT_CFG_80211
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_p2p_init.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_p2p_init.c
new file mode 100755 (executable)
index 0000000..8fd89a4
--- /dev/null
@@ -0,0 +1,518 @@
+/*
+** $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";
+#define AP_MODE_INF_NAME "ap%d";
+//#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
+********************************************************************************
+*/
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+extern int glRegisterEarlySuspend(
+    struct early_suspend        *prDesc,
+    early_suspend_callback      wlanSuspend,
+    late_resume_callback        wlanResume);
+
+extern int glUnregisterEarlySuspend(struct early_suspend *prDesc);
+#endif
+
+/*******************************************************************************
+*                              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
+}
+
+
+extern UINT_8 g_aucBufIpAddr[32];
+
+static void wlanP2PEarlySuspend(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;
+
+    printk(KERN_INFO "*********p2pEarlySuspend************\n");
+
+    if(!wlanExportGlueInfo(&prGlueInfo)) {
+        printk(KERN_INFO "*********p2pEarlySuspend ignored************\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))){
+        printk(KERN_INFO "ip is not avaliable.\n");
+        return;
+    }
+
+    // <4> copy the IPv4 address
+    kalMemCopy(ip, &(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local), sizeof(ip));
+    printk(KERN_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
+    // <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))){
+        printk(KERN_INFO "ipv6 is not avaliable.\n");
+        return;
+    }
+    // <6> copy the IPv6 address
+    kalMemCopy(ip6, &(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local), sizeof(ip6));
+    printk(KERN_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))) {
+    }
+
+#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 + u4NumIPv6;
+        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) ((UINT_32) prParamNetAddr +
+            (UINT_32) (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) ((UINT_32) prParamNetAddr +
+            (UINT_32) (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);
+
+        if (rStatus != WLAN_STATUS_SUCCESS) {
+            printk(KERN_INFO DRV_NAME"set HW pattern filter fail 0x%lx\n", rStatus);
+        }
+    }
+}
+
+
+static void wlanP2PLateResume(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
+
+    printk(KERN_INFO "*********wlanP2PLateResume************\n");
+    if(!wlanExportGlueInfo(&prGlueInfo)) {
+        printk(KERN_INFO "*********p2pLateResume ignored************\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))){
+        printk(KERN_INFO "ip is not avaliable.\n");
+        return;
+    }
+
+    // <4> copy the IPv4 address
+    kalMemCopy(ip, &(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local), sizeof(ip));
+    printk(KERN_INFO"ip is %d.%d.%d.%d\n",
+            ip[0],ip[1],ip[2],ip[3]);
+
+#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))){
+        printk(KERN_INFO "ipv6 is not avaliable.\n");
+        return;
+    }
+    // <6> copy the IPv6 address
+    kalMemCopy(ip6, &(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local), sizeof(ip6));
+    printk(KERN_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);
+
+        if (rStatus != WLAN_STATUS_SUCCESS) {
+            printk(KERN_INFO DRV_NAME"set HW pattern filter fail 0x%lx\n", rStatus);
+        }
+    }
+}
+
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+static struct early_suspend mt6620_p2p_early_suspend_desc = {
+    .level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN,
+};
+
+static void p2p_early_suspend(struct early_suspend *h)
+{
+    printk(KERN_INFO "*********wlanP2P_early_suspend************\n");
+    wlanP2PEarlySuspend();
+}
+
+static void p2p_late_resume(struct early_suspend *h)
+{
+    printk(KERN_INFO "*********wlanP2P_late_resume************\n");
+    wlanP2PLateResume();
+}
+#endif
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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
+    )
+{
+
+    printk("p2p Launch\n");
+
+    if(prGlueInfo->prAdapter->fgIsP2PRegistered == TRUE) {
+        printk("p2p already registered\n");
+        return FALSE;
+    }
+    else if(glRegisterP2P(prGlueInfo, ifname, (BOOLEAN)mode)) {
+        prGlueInfo->prAdapter->fgIsP2PRegistered = TRUE;
+
+        printk("Launch success, fgIsP2PRegistered TRUE.\n");
+
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+        /* Here, we register the early suspend and resume callback  */
+        glRegisterEarlySuspend(&mt6620_p2p_early_suspend_desc, p2p_early_suspend, p2p_late_resume);
+#endif
+
+        return TRUE;
+    }
+    else {
+        printk("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;
+    }
+
+    return;
+} /* 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) {
+        printk("p2p is not Registered.\n");
+        return FALSE;
+    }
+    else {
+
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+        glUnregisterEarlySuspend(&mt6620_p2p_early_suspend_desc);
+#endif
+        /*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;
+    }
+    return FALSE;
+}
+
+#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();
+
+    printk( KERN_INFO DRV_NAME "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;
+
+    printk( 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/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_p2p_kal.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_p2p_kal.c
new file mode 100755 (executable)
index 0000000..bb48193
--- /dev/null
@@ -0,0 +1,1629 @@
+/*
+** $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"
+
+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
+
+/*******************************************************************************
+*                              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
+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
+    );
+
+
+/*******************************************************************************
+*                              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="MACSTR, MAC2STR(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="MACSTR, MAC2STR(rPeerAddr));
+        evt.data.length = strlen(aucBuffer);
+
+        /* indicate in IWECUSTOM event */
+        wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler,
+                IWEVCUSTOM,
+                &evt,
+                aucBuffer);
+    }
+    else {
+        ASSERT(0);
+    }
+
+    return;
+} /* 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);
+
+    return;
+} /* 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
+    )
+{
+    ASSERT(prGlueInfo);
+    ASSERT(prGlueInfo->prP2PInfo);
+
+    prGlueInfo->prP2PInfo->u4CipherPairwise = u4Cipher;
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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
+    )
+{
+    ASSERT(prGlueInfo);
+    ASSERT(prGlueInfo->prP2PInfo);
+
+    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
+    )
+{
+    ASSERT(prGlueInfo);
+    ASSERT(prGlueInfo->prP2PInfo);
+
+    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
+    )
+{
+    ASSERT(prGlueInfo);
+    ASSERT(prGlueInfo->prP2PInfo);
+
+    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
+    )
+{
+    ASSERT(prGlueInfo);
+    ASSERT(prGlueInfo->prP2PInfo);
+
+    prGlueInfo->prP2PInfo->ucWSCRunning = ucWscMode;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief to get the status of WSC
+*
+* \param[in]
+*           prGlueInfo
+*
+* \return
+*/
+/*----------------------------------------------------------------------------*/
+UINT_8
+kalP2PGetWscMode (
+    IN P_GLUE_INFO_T    prGlueInfo
+    )
+{
+    ASSERT(prGlueInfo);
+    ASSERT(prGlueInfo->prP2PInfo);
+
+    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);
+
+    return;
+}
+
+
+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);
+
+    return;
+} /* 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);
+
+    return;
+} /* 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);
+
+    return;
+} /* 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);
+
+    return;
+} /* 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);
+
+    return;
+} /* 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);
+
+    return;
+} /* end of kalP2PIndicateSDResponse() */
+
+
+struct net_device*
+kalP2PGetDevHdlr(
+    P_GLUE_INFO_T prGlueInfo
+    )
+{
+    ASSERT(prGlueInfo);
+    ASSERT(prGlueInfo->prP2PInfo);
+    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);
+    return;
+} /* 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,
+                              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->prDevHandler, //struct net_device * dev,
+                        u8SeqNum, //u64 cookie,
+                        prIEEE80211ChnlStruct, //struct ieee80211_channel * chan,
+                        eChnlType, //enum nl80211_channel_type channel_type,
+                        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->prDevHandler, //struct net_device * dev,
+                        prChnlReqInfo->u8Cookie,
+                        prIEEE80211ChnlStruct,
+                        eChnlType,
+                        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;
+
+    do {
+        if (prGlueInfo == NULL) {
+
+            ASSERT(FALSE);
+            break;
+        }
+
+        prGlueP2pInfo = prGlueInfo->prP2PInfo;
+
+        if (prGlueP2pInfo == NULL) {
+            ASSERT(FALSE);
+            break;
+        }
+
+
+        if (prGlueP2pInfo->prScanRequest) {
+            cfg80211_scan_done(prGlueP2pInfo->prScanRequest,
+                        fgIsAbort);
+
+            prGlueP2pInfo->prScanRequest = NULL;
+        }
+
+    } 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, TRACE, ("Unknown channel info\n"));
+            break;
+        }
+
+
+        //rChannelInfo.center_freq = nicChannelNum2Freq((UINT_32)prChannelInfo->ucChannelNum) / 1000;
+
+        prCfg80211Bss = cfg80211_inform_bss_frame(prGlueP2pInfo->wdev.wiphy, //struct wiphy * wiphy,
+                                prChannelEntry,
+                                prBcnProbeRspFrame,
+                                u4BufLen,
+                                i4SignalStrength,
+                                GFP_KERNEL);
+
+
+        /* Return this structure. */
+        cfg80211_put_bss(prCfg80211Bss);
+
+    } while (FALSE);
+
+    return;
+
+} /* 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. 0x%lx, 0x%lx, %ld.", prGlueInfo, pucFrameBuf, u4FrameLen));
+            ASSERT(FALSE);
+            break;
+        }
+
+        prGlueP2pInfo = prGlueInfo->prP2PInfo;
+
+        cfg80211_mgmt_tx_status(prGlueP2pInfo->prDevHandler, //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: "MACSTR"\n", MAC2STR(prWlanHeader->aucAddr2)));
+#endif
+        i4Freq = nicChannelNum2Freq(ucChnlNum) / 1000;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+        cfg80211_rx_mgmt(prGlueP2pInfo->prDevHandler, //struct net_device * dev,
+                            i4Freq,
+                            RCPI_TO_dBm(prSwRfb->prHifRxHdr->ucRcpi),
+                            prSwRfb->pvHeader,
+                            prSwRfb->u2PacketLen,
+                            GFP_ATOMIC);
+#else
+        cfg80211_rx_mgmt(prGlueP2pInfo->prDevHandler, //struct net_device * dev,
+                            i4Freq,
+                            prSwRfb->pvHeader,
+                            prSwRfb->u2PacketLen,
+                            GFP_ATOMIC);
+#endif
+
+    } 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
+    )
+{
+    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,
+                                    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;
+
+    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;
+
+    do {
+        if ((prP2pInfo == NULL) || (prChannelInfo == NULL)) {
+            break;
+        }
+
+
+        switch (prChannelInfo->eBand) {
+        case BAND_2G4:
+            prTargetChannelEntry = prP2pInfo->wdev.wiphy->bands[IEEE80211_BAND_2GHZ]->channels;
+            u4TblSize = prP2pInfo->wdev.wiphy->bands[IEEE80211_BAND_2GHZ]->n_channels;
+            break;
+        case BAND_5G:
+            prTargetChannelEntry = prP2pInfo->wdev.wiphy->bands[IEEE80211_BAND_5GHZ]->channels;
+            u4TblSize = prP2pInfo->wdev.wiphy->bands[IEEE80211_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
+*/
+/*----------------------------------------------------------------------------*/
+BOOLEAN
+kalP2PSetBlackList (
+    IN P_GLUE_INFO_T    prGlueInfo,
+    IN PARAM_MAC_ADDRESS rbssid,
+    IN BOOLEAN fgIsblock
+    )
+{
+    UINT_8  aucNullAddr[] = NULL_MAC_ADDR;
+    BOOLEAN fgIsValid = FALSE;
+    UINT_32 i;
+
+    ASSERT(prGlueInfo);
+    ASSERT(prGlueInfo->prP2PInfo);
+
+    if(fgIsblock) {
+        for(i = 0; i < 8; i++) {
+            if(UNEQUAL_MAC_ADDR(rbssid, aucNullAddr)) {
+                if(UNEQUAL_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucblackMACList[i]), rbssid)) {
+                    if(EQUAL_MAC_ADDR (&(prGlueInfo->prP2PInfo->aucblackMACList[i]), aucNullAddr)) {
+                        COPY_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucblackMACList[i]), rbssid);
+                        fgIsValid = FALSE;
+                        return fgIsValid;
+                    }
+                }
+            }
+        }
+    } 
+    else {
+        for(i = 0; i < 8; i++) {
+            if(EQUAL_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucblackMACList[i]), rbssid)) {
+                COPY_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucblackMACList[i]), aucNullAddr);
+                fgIsValid = FALSE;
+                return fgIsValid;
+            }
+        } 
+    }
+
+    return fgIsValid;
+
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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
+    )
+{
+    ASSERT(prGlueInfo);
+    ASSERT(prGlueInfo->prP2PInfo);
+
+    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
+    )
+{
+    ASSERT(prGlueInfo);
+    ASSERT(prGlueInfo->prP2PInfo);
+
+    if(prGlueInfo->prP2PInfo->ucMaxClients) {
+        if((UINT_8)u4NumClient > prGlueInfo->prP2PInfo->ucMaxClients)
+            return TRUE;
+        else
+            return FALSE;
+    }
+
+    return FALSE;
+}
+
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_proc.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_proc.c
new file mode 100755 (executable)
index 0000000..3e53176
--- /dev/null
@@ -0,0 +1,811 @@
+/*
+** $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 "gl_os.h"
+#include "gl_kal.h"
+
+#include "wlan_lib.h"
+#include "debug.h"
+
+
+/*******************************************************************************
+*                              C O N S T A N T S
+********************************************************************************
+*/
+#define PROC_MCR_ACCESS                         "mcr"
+#define PROC_DRV_STATUS                         "status"
+#define PROC_RX_STATISTICS                      "rx_statistics"
+#define PROC_TX_STATISTICS                      "tx_statistics"
+#define PROC_DBG_LEVEL                          "dbg_level"
+
+#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
+#define PROC_DBG_LEVEL_MAX_DISPLAY_STR_LEN      30
+
+
+/*******************************************************************************
+*                             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 = 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
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                              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.
+*/
+/*----------------------------------------------------------------------------*/
+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_STRUC_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_STRUC_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';
+
+    switch (sscanf(acBuf, "0x%lx 0x%lx",
+                   &rMcrInfo.u4McrOffset, &rMcrInfo.u4McrData)) {
+    case 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);
+
+        }
+        break;
+
+    case 1:
+        //if (IS_ALIGN_4(rMcrInfo.u4McrOffset))
+        {
+            u4McrOffset = rMcrInfo.u4McrOffset;
+        }
+        break;
+
+    default:
+        break;
+    }
+
+    return count;
+
+} /* end of procMCRWrite() */
+
+#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 (sscanf(acBuf, "%ld", &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 (sscanf(acBuf, "%ld", &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
+
+
+#if DBG
+static UINT_8 aucDbModuleName[][PROC_DBG_LEVEL_MAX_DISPLAY_STR_LEN] = {
+    "DBG_INIT_IDX",
+    "DBG_HAL_IDX",
+    "DBG_INTR_IDX",
+    "DBG_REQ_IDX",    
+    "DBG_TX_IDX",
+    "DBG_RX_IDX",
+    "DBG_RFTEST_IDX",
+    "DBG_EMU_IDX",    
+    "DBG_SW1_IDX",
+    "DBG_SW2_IDX",
+    "DBG_SW3_IDX",
+    "DBG_SW4_IDX",    
+    "DBG_HEM_IDX",
+    "DBG_AIS_IDX",
+    "DBG_RLM_IDX",
+    "DBG_MEM_IDX",
+    "DBG_CNM_IDX",    
+    "DBG_RSN_IDX",
+    "DBG_BSS_IDX",
+    "DBG_SCN_IDX",
+    "DBG_SAA_IDX",
+    "DBG_AAA_IDX",
+    "DBG_P2P_IDX",
+    "DBG_QM_IDX",
+    "DBG_SEC_IDX",
+    "DBG_BOW_IDX"
+    };
+    
+extern UINT_8 aucDebugModule[];
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief The PROC function for displaying current Debug Level.
+*
+* \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
+procDbgLevelRead (
+    char *page,
+    char **start,
+    off_t off,
+    int count,
+    int *eof,
+    void *data
+    )
+{
+    char *p = page;
+    int i;
+
+
+
+    // Kevin: Apply PROC read method 1.
+    if (off != 0) {
+        return 0; // To indicate end of file.
+    }
+
+    for (i = 0; i < (sizeof(aucDbModuleName)/PROC_DBG_LEVEL_MAX_DISPLAY_STR_LEN); i++) {
+        SPRINTF(p, ("%c %-15s(0x%02x): %02x\n",
+            ((i == u4DebugModule) ? '*' : ' '),
+            &aucDbModuleName[i][0],
+            i,
+            aucDebugModule[i]));
+    }
+
+    *eof = 1;
+    return (int)(p - page);
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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 int
+procDbgLevelWrite (
+    struct file *file,
+    const char *buffer,
+    unsigned long count,
+    void *data
+    )
+{
+    char acBuf[PROC_DBG_LEVEL_MAX_USER_INPUT_LEN + 1]; // + 1 for "\0"
+    UINT_32 u4CopySize;
+    UINT_32 u4NewDbgModule, u4NewDbgLevel;
+
+
+    u4CopySize = (count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1);
+    copy_from_user(acBuf, buffer, u4CopySize);
+    acBuf[u4CopySize] = '\0';
+
+    if (sscanf(acBuf, "0x%lx 0x%lx", &u4NewDbgModule, &u4NewDbgLevel) == 2) {
+        if (u4NewDbgModule < DBG_MODULE_NUM) {
+            u4DebugModule = u4NewDbgModule;
+            u4NewDbgLevel &= DBG_CLASS_MASK;
+            aucDebugModule[u4DebugModule] = (UINT_8)u4NewDbgLevel;
+        }
+    }
+
+    return count;
+}
+#endif /* DBG */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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
+*/
+/*----------------------------------------------------------------------------*/
+INT_32
+procInitProcfs (
+    struct net_device *prDev,
+    char *pucDevName
+    )
+{
+    P_GLUE_INFO_T prGlueInfo;
+    struct proc_dir_entry *prEntry;
+
+
+    ASSERT(prDev);
+
+    if (init_net.proc_net == (struct proc_dir_entry *)NULL) {
+        DBGLOG(INIT, INFO, ("init proc fs fail: proc_net == NULL\n"));
+        return -ENOENT;
+    }
+
+    prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+
+    if (!prGlueInfo) {
+        DBGLOG(INIT, WARN, ("The OS context is NULL\n"));
+        return -ENOENT;
+    }
+
+
+    /*
+    /proc/net/wlan0
+               |-- mcr              (PROC_MCR_ACCESS)
+               |-- status           (PROC_DRV_STATUS)
+               |-- rx_statistics    (PROC_RX_STATISTICS)
+               |-- tx_statistics    (PROC_TX_STATISTICS)
+               |-- dbg_level        (PROC_DBG_LEVEL)
+               |-- (end)
+     */
+
+    /*
+    * Directory: Root (/proc/net/wlan0)
+    */
+
+    prGlueInfo->pProcRoot = proc_mkdir(pucDevName, init_net.proc_net);
+    if (prGlueInfo->pProcRoot == NULL) {
+        return -ENOENT;
+    }
+
+    /* File Root/mcr (RW) */
+    prEntry = create_proc_entry(PROC_MCR_ACCESS, 0, prGlueInfo->pProcRoot);
+    if (prEntry) {
+        prEntry->read_proc = procMCRRead;
+        prEntry->write_proc = procMCRWrite;
+        prEntry->data = (void *)prDev;
+    }
+
+#if 0
+    /* File Root/status (RW) */
+    prEntry = create_proc_read_entry(PROC_DRV_STATUS, 0, prGlueInfo->pProcRoot,
+                                     procDrvStatusRead, prDev);
+
+    /* File Root/rx_statistics (RW) */
+    prEntry = create_proc_entry(PROC_RX_STATISTICS, 0, prGlueInfo->pProcRoot);
+    if (prEntry) {
+        prEntry->read_proc = procRxStatisticsRead;
+        prEntry->write_proc = procRxStatisticsWrite;
+        prEntry->data = (void *)prDev;
+    }
+
+    /* File Root/tx_statistics (RW) */
+    prEntry = create_proc_entry(PROC_TX_STATISTICS, 0, prGlueInfo->pProcRoot);
+    if (prEntry) {
+        prEntry->read_proc = procTxStatisticsRead;
+        prEntry->write_proc = procTxStatisticsWrite;
+        prEntry->data = (void *)prDev;
+    }
+
+#if DBG
+    /* File Root/dbg_level (RW) */
+    prEntry = create_proc_entry(PROC_DBG_LEVEL, 0644, prGlueInfo->pProcRoot);
+    if (prEntry) {
+        prEntry->read_proc = procDbgLevelRead;
+        prEntry->write_proc = procDbgLevelWrite;
+    }
+#endif /* DBG */
+#endif
+    return 0;
+
+} /* end of procInitProcfs() */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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 (
+    struct net_device *prDev,
+    char *pucDevName
+    )
+{
+    P_GLUE_INFO_T prGlueInfo = NULL;
+
+
+    ASSERT(prDev);
+
+    if (!prDev) {
+        return -ENOENT;
+    }
+
+    if (init_net.proc_net == (struct proc_dir_entry *)NULL) {
+        DBGLOG(INIT, WARN, ("remove proc fs fail: proc_net == NULL\n"));
+        return -ENOENT;
+    }
+
+    prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+    if (!prGlueInfo->pProcRoot) {
+        DBGLOG(INIT, WARN, ("The procfs root is NULL\n"));
+        return -ENOENT;
+    }
+#if 0
+#if DBG
+    remove_proc_entry(PROC_DBG_LEVEL,       prGlueInfo->pProcRoot);
+#endif /* DBG */
+    remove_proc_entry(PROC_TX_STATISTICS,   prGlueInfo->pProcRoot);
+    remove_proc_entry(PROC_RX_STATISTICS,   prGlueInfo->pProcRoot);
+    remove_proc_entry(PROC_DRV_STATUS,      prGlueInfo->pProcRoot);
+#endif
+    remove_proc_entry(PROC_MCR_ACCESS,      prGlueInfo->pProcRoot);
+
+    /* remove root directory (proc/net/wlan0) */
+    remove_proc_entry(pucDevName, init_net.proc_net);
+
+    return 0;
+
+} /* end of procRemoveProcfs() */
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_rst.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_rst.c
new file mode 100755 (executable)
index 0000000..eadc2c6
--- /dev/null
@@ -0,0 +1,473 @@
+/*
+** $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 "gl_os.h"
+#include "debug.h"
+#include "wlan_lib.h"
+#include "gl_wext.h"
+#include "precomp.h"
+#include <linux/poll.h>
+#include <net/netlink.h>
+#include <net/genetlink.h>
+
+#if CFG_CHIP_RESET_SUPPORT
+
+/*******************************************************************************
+*                              C O N S T A N T S
+********************************************************************************
+*/
+#define MAX_BIND_PROCESS    (4)
+
+#define MTK_WIFI_FAMILY_NAME        "MTK_WIFI"
+#define MTK_WIFI_RESET_START_NAME   "RESET_START"
+#define MTK_WIFI_RESET_END_NAME     "RESET_END"
+#define MTK_WIFI_RESET_TEST_NAME    "GENETLINK_START"
+
+
+/*******************************************************************************
+*                             D A T A   T Y P E S
+********************************************************************************
+*/
+enum {
+    __MTK_WIFI_ATTR_INVALID,
+    MTK_WIFI_ATTR_MSG,
+    __MTK_WIFI_ATTR_MAX,
+};
+#define MTK_WIFI_ATTR_MAX       (__MTK_WIFI_ATTR_MAX - 1)
+
+
+enum {
+    __MTK_WIFI_COMMAND_INVALID,
+    MTK_WIFI_COMMAND_BIND,
+    MTK_WIFI_COMMAND_RESET,
+    __MTK_WIFI_COMMAND_MAX,
+};
+#define MTK_WIFI_COMMAND_MAX    (__MTK_WIFI_COMMAND_MAX - 1)
+
+/*******************************************************************************
+*                            P U B L I C   D A T A
+********************************************************************************
+*/BOOLEAN fgIsResetting = FALSE;
+
+/*******************************************************************************
+*                           P R I V A T E   D A T A
+********************************************************************************
+*/
+static UINT_32 mtk_wifi_seqnum = 0;
+static int num_bind_process = 0;
+static pid_t bind_pid[MAX_BIND_PROCESS];
+
+
+/* attribute policy */
+static struct nla_policy mtk_wifi_genl_policy[MTK_WIFI_ATTR_MAX + 1] = {
+    [MTK_WIFI_ATTR_MSG] = { .type = NLA_NUL_STRING },
+};
+
+/* family definition */
+static struct genl_family mtk_wifi_gnl_family = {
+    .id         = GENL_ID_GENERATE,
+    .hdrsize    = 0,
+    .name       = MTK_WIFI_FAMILY_NAME,
+    .version    = 1,
+    .maxattr    = MTK_WIFI_ATTR_MAX,
+};
+
+/* forward declaration */
+static int mtk_wifi_bind(
+    struct sk_buff *skb,
+    struct genl_info *info
+    );
+
+static int mtk_wifi_reset(
+    struct sk_buff *skb,
+    struct genl_info *info
+    );
+
+/* operation definition */
+static struct genl_ops mtk_wifi_gnl_ops_bind = {
+    .cmd = MTK_WIFI_COMMAND_BIND,
+    .flags  = 0,
+    .policy = mtk_wifi_genl_policy,
+    .doit   = mtk_wifi_bind,
+    .dumpit = NULL,
+};
+
+static struct genl_ops mtk_wifi_gnl_ops_reset = {
+    .cmd = MTK_WIFI_COMMAND_RESET,
+    .flags  = 0,
+    .policy = mtk_wifi_genl_policy,
+    .doit   = mtk_wifi_reset,
+    .dumpit = NULL,
+};
+
+
+/*******************************************************************************
+*                                 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
+********************************************************************************
+*/
+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
+    );
+
+static void *
+glResetCallback (
+    ENUM_WMTDRV_TYPE_T  eSrcType,
+    ENUM_WMTDRV_TYPE_T  eDstType,
+    ENUM_WMTMSG_TYPE_T  eMsgType,
+    void *              prMsgBody,
+    unsigned int        u4MsgLength
+    );
+
+static BOOLEAN
+glResetSendMessage (
+    char    *aucMsg,
+    u8      cmd
+    );
+
+
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+/*----------------------------------------------------------------------------*/
+/*!
+ * @brief This routine is responsible for 
+ *        1. registering for reset callbacks
+ *        2. initialize netlink socket 
+ *
+ * @param none
+ *
+ * @retval none
+ */
+/*----------------------------------------------------------------------------*/
+VOID
+glResetInit(
+    VOID
+    )
+{
+    /* 1. register for reset callback */
+    mtk_wcn_wmt_msgcb_reg(WMTDRV_TYPE_WIFI, (PF_WMT_CB)glResetCallback);
+
+    /* 2.1 registration for NETLINK_GENERIC family */
+    if(genl_register_family(&mtk_wifi_gnl_family) != 0) {
+        DBGLOG(INIT, WARN, ("%s(): GE_NELINK family registration fail\n", __func__));
+    }
+    else {
+        /* 2.2 operation registration */
+        if(genl_register_ops(&mtk_wifi_gnl_family, &mtk_wifi_gnl_ops_bind) != 0) {
+            DBGLOG(INIT, WARN, ("%s(): BIND operation registration fail\n", __func__));
+        }
+
+        if(genl_register_ops(&mtk_wifi_gnl_family, &mtk_wifi_gnl_ops_reset) != 0) {
+            DBGLOG(INIT, WARN, ("%s(): RESET operation registration fail\n", __func__));
+        }
+    }
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+ * @brief This routine is responsible for 
+ *        1. uninitialize netlink socket 
+ *        2. deregistering for reset callbacks
+ *
+ * @param none
+ *
+ * @retval none
+ */
+/*----------------------------------------------------------------------------*/
+VOID
+glResetUninit(
+    VOID
+    )
+{
+    /* 1. release NETLINK_GENERIC family */
+    genl_unregister_family(&mtk_wifi_gnl_family);
+
+    /* 2. deregister for reset callback */
+    mtk_wcn_wmt_msgcb_unreg(WMTDRV_TYPE_WIFI);
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+ * @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:
+                fgIsResetting = TRUE;
+                glResetSendMessage(MTK_WIFI_RESET_START_NAME, MTK_WIFI_COMMAND_RESET);
+                break;
+
+            case WMTRSTMSG_RESET_END:
+                glResetSendMessage(MTK_WIFI_RESET_END_NAME, MTK_WIFI_COMMAND_RESET);
+                fgIsResetting = FALSE;
+                break;
+
+            default:
+                break;
+            }
+        }
+
+        break;
+
+    default:
+        break;
+    }
+
+    return NULL;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+ * @brief This routine send out message via netlink socket
+ *
+ * @param   aucMsg
+ *          u4MsgLength
+ *
+ * @retval  TRUE
+ *          FALSE
+ */
+/*----------------------------------------------------------------------------*/
+static BOOLEAN
+glResetSendMessage(
+    char *  aucMsg,
+    u8      cmd
+    )
+{
+    struct sk_buff *skb = NULL;
+    void *msg_head = NULL;
+    int rc = -1;
+    int i;
+
+    if(num_bind_process == 0) {
+        /* no listening process */
+        return FALSE;
+    }
+
+    for(i = 0 ; i < num_bind_process ; i++) {
+        skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+
+        if(skb) {
+            msg_head = genlmsg_put(skb, 0, mtk_wifi_seqnum++, &mtk_wifi_gnl_family, 0, cmd);
+
+            if(msg_head == NULL) {
+                nlmsg_free(skb);
+                return FALSE;
+            }
+
+            rc = nla_put_string(skb, MTK_WIFI_ATTR_MSG, aucMsg);
+            if(rc != 0) {
+                nlmsg_free(skb);
+                return FALSE;
+            }
+        
+            /* finalize the message */
+            genlmsg_end(skb, msg_head);
+        
+            /* sending message */
+            rc = genlmsg_unicast(&init_net, skb, bind_pid[i]);
+            if(rc != 0) {
+                return FALSE;
+            }
+        }
+        else {
+            return FALSE;
+        }
+    }
+
+    return TRUE;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+ * @brief This routine is called to identify PID for process binding
+ *
+ * @param   skb
+ *          info
+ *
+ * @retval  0
+ *          nonzero
+ */
+/*----------------------------------------------------------------------------*/
+int mtk_wifi_bind(
+    struct sk_buff *skb,
+    struct genl_info *info
+    )
+{
+    struct nlattr *na;
+    char * mydata;
+
+    if (info == NULL) {
+        goto out;
+    }
+
+    /*for each attribute there is an index in info->attrs which points to a nlattr structure
+     *in this structure the data is given
+     */
+    
+    na = info->attrs[MTK_WIFI_ATTR_MSG];
+    if (na) {
+        mydata = (char *)nla_data(na);
+
+        /* no need to parse mydata */
+    }
+
+    /* collect PID */
+    if(num_bind_process < MAX_BIND_PROCESS) {
+        bind_pid[num_bind_process] = info->snd_pid;
+        num_bind_process++;
+        }
+    else {
+        DBGLOG(INIT, WARN, ("%s(): exceeding binding limit %d\n", __func__, MAX_BIND_PROCESS));
+    }
+
+out:
+    return 0;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+ * @brief This routine is called for reset, shout not happen
+ *
+ * @param   skb
+ *          info
+ *
+ * @retval  0
+ *          nonzero
+ */
+/*----------------------------------------------------------------------------*/
+int mtk_wifi_reset(
+    struct sk_buff *skb,
+    struct genl_info *info
+    )
+{
+    DBGLOG(INIT, WARN, ("%s(): should not be invoked\n", __func__));
+
+    return 0;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+ * @brief This routine is called for generating reset request to WMT
+ *
+ * @param   None
+ *
+ * @retval  None
+ */
+/*----------------------------------------------------------------------------*/
+VOID
+glSendResetRequest(
+    VOID
+    )
+{
+    // WMT thread would trigger whole chip resetting itself
+    return;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+ * @brief This routine is called for checking if MT6620 is resetting
+ *
+ * @param   None
+ *
+ * @retval  TRUE
+ *          FALSE
+ */
+/*----------------------------------------------------------------------------*/
+BOOLEAN
+kalIsResetting(
+    VOID
+    )
+{
+    return fgIsResetting;
+}
+
+
+#endif // CFG_CHIP_RESET_SUPPORT
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_wext.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_wext.c
new file mode 100755 (executable)
index 0000000..17e3460
--- /dev/null
@@ -0,0 +1,4527 @@
+/*
+** $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
+ * Initilize 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 continous memory demands
+ * separate kalMemAlloc() into virtually-continous and physically-continous 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 continous memory demands
+ * separate kalMemAlloc() into virtually-continous and physically-continous 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 (throught 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     MAP_CHANNEL_ID_TO_KHZ(ch, khz)  {               \
+                switch (ch)                                 \
+                {                                           \
+                    case 1:     khz = 2412000;   break;     \
+                    case 2:     khz = 2417000;   break;     \
+                    case 3:     khz = 2422000;   break;     \
+                    case 4:     khz = 2427000;   break;     \
+                    case 5:     khz = 2432000;   break;     \
+                    case 6:     khz = 2437000;   break;     \
+                    case 7:     khz = 2442000;   break;     \
+                    case 8:     khz = 2447000;   break;     \
+                    case 9:     khz = 2452000;   break;     \
+                    case 10:    khz = 2457000;   break;     \
+                    case 11:    khz = 2462000;   break;     \
+                    case 12:    khz = 2467000;   break;     \
+                    case 13:    khz = 2472000;   break;     \
+                    case 14:    khz = 2484000;   break;     \
+                    case 36:  /* UNII */  khz = 5180000;   break;     \
+                    case 40:  /* UNII */  khz = 5200000;   break;     \
+                    case 44:  /* UNII */  khz = 5220000;   break;     \
+                    case 48:  /* UNII */  khz = 5240000;   break;     \
+                    case 52:  /* UNII */  khz = 5260000;   break;     \
+                    case 56:  /* UNII */  khz = 5280000;   break;     \
+                    case 60:  /* UNII */  khz = 5300000;   break;     \
+                    case 64:  /* UNII */  khz = 5320000;   break;     \
+                    case 149: /* UNII */  khz = 5745000;   break;     \
+                    case 153: /* UNII */  khz = 5765000;   break;     \
+                    case 157: /* UNII */  khz = 5785000;   break;     \
+                    case 161: /* UNII */  khz = 5805000;   break;     \
+                    case 165: /* UNII */  khz = 5825000;   break;     \
+                    case 100: /* HiperLAN2 */  khz = 5500000;   break;     \
+                    case 104: /* HiperLAN2 */  khz = 5520000;   break;     \
+                    case 108: /* HiperLAN2 */  khz = 5540000;   break;     \
+                    case 112: /* HiperLAN2 */  khz = 5560000;   break;     \
+                    case 116: /* HiperLAN2 */  khz = 5580000;   break;     \
+                    case 120: /* HiperLAN2 */  khz = 5600000;   break;     \
+                    case 124: /* HiperLAN2 */  khz = 5620000;   break;     \
+                    case 128: /* HiperLAN2 */  khz = 5640000;   break;     \
+                    case 132: /* HiperLAN2 */  khz = 5660000;   break;     \
+                    case 136: /* HiperLAN2 */  khz = 5680000;   break;     \
+                    case 140: /* HiperLAN2 */  khz = 5700000;   break;     \
+                    case 34:  /* Japan MMAC */   khz = 5170000;   break;   \
+                    case 38:  /* Japan MMAC */   khz = 5190000;   break;   \
+                    case 42:  /* Japan MMAC */   khz = 5210000;   break;   \
+                    case 46:  /* Japan MMAC */   khz = 5230000;   break;   \
+                    case 184: /* Japan */   khz = 4920000;   break;   \
+                    case 188: /* Japan */   khz = 4940000;   break;   \
+                    case 192: /* Japan */   khz = 4960000;   break;   \
+                    case 196: /* Japan */   khz = 4980000;   break;   \
+                    case 208: /* Japan, means J08 */   khz = 5040000;   break;   \
+                    case 212: /* Japan, means J12 */   khz = 5060000;   break;   \
+                    case 216: /* Japan, means J16 */   khz = 5080000;   break;   \
+                    default:    khz = 2412000;   break;     \
+                }                                           \
+            }
+
+
+#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,                       ""},
+
+    /* 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
+};
+
+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,
+};
+
+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;
+            }
+            else {
+                /* 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_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;
+            }
+            else {
+                /* 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;
+
+    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;
+    }
+    else {
+        /* 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(INIT, INFO, ("%s(): Set UNSUPPORTED Mode = %d.\n", __FUNCTION__, *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;
+
+    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(INIT, INFO, ("%s(): Get UNKNOWN Mode.\n", __FUNCTION__));
+        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);
+        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(INIT, INFO, ("[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;
+    }
+    else {
+        DBGLOG(INIT, INFO, ("[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(INIT, INFO, ("[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(INIT, INFO, ("[wifi] no memory for larger scan list :%ld\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(INIT, INFO, ("[wifi] larger buf:%d result:%ld\n", u4AllocBufLen, u4BufLen));
+            ret = -E2BIG;
+            prData->length = (__u16)u4BufLen;
+            goto error;
+        }
+#endif /* WIRELESS_EXT >= 17 */
+
+    }
+
+
+    if (prList->u4NumberOfItems > CFG_MAX_NUM_BSS_LIST) {
+        DBGLOG(INIT, INFO, ("[wifi] strange scan result count:%ld\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;
+        memcpy(iwEvent.u.ap_addr.sa_data, prBss->arMacAddress, ETH_ALEN);
+        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 lengh 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;
+        }
+        else {
+            /* 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;
+    }
+    else {
+        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;
+
+    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(INIT, INFO, ("######set disassoc failed\n"));
+        } else {
+            DBGLOG(INIT, INFO, ("######set assoc ok\n"));
+        }
+
+        /* <2> mark to power state flag*/
+        ePowerState = ACPI_STATE_D0;
+        DBGLOG(INIT, INFO, ("set to acpi d3(0)\n"));
+        wlanSetAcpiState(prGlueInfo->prAdapter, ePowerState);
+
+    }
+    else {
+        ePowerState = ACPI_STATE_D0;
+        DBGLOG(INIT, 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;
+
+    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(INIT, INFO, ("wlanoidSetAddWep fail 0x%lx\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(INIT, INFO, ("%s(): unsupported power management mode value = %d.\n",
+                __FUNCTION__,
+                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(INIT, 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(INIT, 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 */
+        memcpy(prWpiKey->aucPN, prIWEncExt->tx_seq, IW_ENCODE_SEQ_MAX_SIZE * 2);
+
+        /* 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) {
+            //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:[" MACSTR "]\n",
+            prRemoveKey->KeyIndex, MAC2STR(prRemoveKey->BSSID));
+        */
+
+        rStatus = kalIoctl(prGlueInfo,
+                     wlanoidSetRemoveKey,
+                     prRemoveKey,
+                     prRemoveKey->u4Length,
+                     FALSE,
+                     FALSE,
+                     TRUE,
+                     FALSE,
+                     &u4BufLen);
+
+
+        if (rStatus != WLAN_STATUS_SUCCESS) {
+            DBGLOG(INIT, INFO, ("remove key error:%lx\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(INIT, INFO, ("wlanoidSetAddWep fail 0x%lx\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(INIT, INFO, ("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) {
+                    DBGLOG(INIT, INFO, ("wlanoidSetEncryptionStatus fail 0x%lx\n", rStatus));
+                    return -EFAULT;
+                }
+
+            } else {
+                DBGLOG(INIT, INFO, ("key length %x\n", prIWEncExt->key_len));
+                DBGLOG(INIT, 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(INIT, INFO, ("key index error:0x%lx\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;
+                }
+
+                /* 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);
+
+            /* 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 = ((UINT_32)&(((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(INIT, INFO, ("add key error:%lx\n", rStatus));
+                return -EFAULT;
+            }
+            break;
+        }
+    }
+
+    return 0;
+} /* wext_set_encode_ext */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief Set country code
+*
+* \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_country (
+    IN struct net_device *prNetDev,
+    IN struct iwreq      *iwr
+    )
+{
+    P_GLUE_INFO_T   prGlueInfo;
+    WLAN_STATUS     rStatus;
+    UINT_32         u4BufLen;
+    UINT_8          aucCountry[2];
+
+    ASSERT(prNetDev);
+
+    /* iwr->u.data.pointer should be like "COUNTRY US", "COUNTRY EU"
+     * and "COUNTRY JP"
+     */
+    if (FALSE == GLUE_CHK_PR2(prNetDev, iwr) ||
+        !iwr->u.data.pointer || iwr->u.data.length < 10) {
+        return -EINVAL;
+    }
+    prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
+
+    aucCountry[0] = *((PUINT_8)iwr->u.data.pointer + 8);
+    aucCountry[1] = *((PUINT_8)iwr->u.data.pointer + 9);
+
+    rStatus = kalIoctl(prGlueInfo,
+        wlanoidSetCountryCode,
+        &aucCountry[0],
+        2,
+        FALSE,
+        FALSE,
+        TRUE,
+        FALSE,
+        &u4BufLen);
+
+    return 0;
+}
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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
+    )
+{
+    /* prIfReq is verified in the caller function wlanDoIOCTL() */
+    struct iwreq *iwr = (struct iwreq*)prIfReq;
+    struct iw_request_info rIwReqInfo;
+    int ret = 0;
+    char *prExtraBuf = NULL;
+    UINT_32 u4ExtraSize = 0;
+
+    /* prDev is verified in the caller function wlanDoIOCTL() */
+
+    printk("%d CMD:0x%x\n", jiffies_to_msecs(jiffies), i4Cmd);
+
+    /* Prepare the call */
+    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 shoule 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, Country */
+        ret = wext_set_country(prDev, iwr);
+        break;
+
+    /* case SIOCGIWPRIV: 0x8B0D, handled in wlan_do_ioctl() */
+    /* caes 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;
+        }
+        else {
+            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(INIT, INFO, ("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(INIT, INFO, ("[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(INIT, INFO, ("Updated result length is larger than allocated (%d > %ld)\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(INIT, INFO, ("[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) {
+            P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+            if (1 /* wlanQueryWapiMode(prGlueInfo->prAdapter) */) {
+                /* 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) {
+                    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 {
+                        WLAN_STATUS    rStatus;
+                        UINT_32        u4BufLen;
+#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 [" MACSTR "]\n",
+                        MAC2STR(((struct iw_pmksa *)pExtraBuf)->bssid.sa_data));
+                    */
+                    {
+                    P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+                    WLAN_STATUS    rStatus;
+                    UINT_32        u4BufLen;
+                    P_PARAM_PMKID_T  prPmkid;
+
+                    prPmkid =(P_PARAM_PMKID_T)kalMemAlloc(8 + sizeof(PARAM_BSSID_INFO_T), VIR_MEM_TYPE);
+                    if (!prPmkid) {
+                        DBGLOG(INIT, INFO, ("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(INIT, INFO, ("add pmkid error:%lx\n", rStatus));
+                    }
+                    kalMemFree(prPmkid, VIR_MEM_TYPE, 8 + sizeof(PARAM_BSSID_INFO_T));
+                    }
+                    break;
+                case IW_PMKSA_REMOVE:
+                    /*
+                    printk(KERN_INFO "IW_PMKSA_REMOVE [" MACSTR "]\n",
+                        MAC2STR(((struct iw_pmksa *)buf)->bssid.sa_data));
+                    */
+                    break;
+                case IW_PMKSA_FLUSH:
+                    /*
+                    printk(KERN_INFO "IW_PMKSA_FLUSH\n");
+                    */
+                    {
+                    P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+                    WLAN_STATUS    rStatus;
+                    UINT_32        u4BufLen;
+                    P_PARAM_PMKID_T  prPmkid;
+
+                    prPmkid =(P_PARAM_PMKID_T)kalMemAlloc(8, VIR_MEM_TYPE);
+                    if (!prPmkid) {
+                        DBGLOG(INIT, INFO, ("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(INIT, INFO, ("flush pmkid error:%lx\n", rStatus));
+                    }
+                    kalMemFree(prPmkid, VIR_MEM_TYPE, 8);
+                    }
+                    break;
+                default:
+                    DBGLOG(INIT, INFO, ("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
+*      <net/iw_handler.h> 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) {
+            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 */
+        }
+#if 0
+        else if (wextSrchDesiredWPSIE(pucData, u4dataLen, 0xDD, &pucDesiredIE)) {
+            /* WPS IE found */
+        }
+#endif
+        else if (wextSrchDesiredWPAIE(pucData, u4dataLen, 0xDD, &pucDesiredIE)) {
+            /* WPA IE found */
+        }
+#if CFG_SUPPORT_WAPI /* Android+ */
+        else if (wextSrchDesiredWAPIIE(pucData, u4dataLen, &pucDesiredIE)) {
+            //printk("wextSrchDesiredWAPIIE!!\n");
+            /* WAPI IE found */
+        }
+#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;
+            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 */
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief To report the private supported IOCTLs table to user space.
+*
+* \param[in] prNetDev Net device requested.
+* \param[out] prIfReq Pointer to ifreq structure, content is copied back to
+*                  user space buffer in gl_iwpriv_table.
+*
+* \retval 0 For success.
+* \retval -E2BIG For user's buffer size is too small.
+* \retval -EFAULT For fail.
+*
+*/
+/*----------------------------------------------------------------------------*/
+int
+wext_get_priv (
+    IN struct net_device *prNetDev,
+    IN struct ifreq *prIfReq
+    )
+{
+    /* prIfReq is verified in the caller function wlanDoIOCTL() */
+    struct iwreq *prIwReq = (struct iwreq *)prIfReq;
+    struct iw_point *prData= (struct iw_point *)&prIwReq->u.data;
+    UINT_16 u2BufferSize = 0;
+
+    u2BufferSize = prData->length;
+
+    /* update our private table size */
+    prData->length = (__u16)sizeof(rIwPrivTable)/sizeof(struct iw_priv_args);
+
+    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 */
+
+#endif /* WIRELESS_EXT */
+
+
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_wext_priv.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/gl_wext_priv.c
new file mode 100755 (executable)
index 0000000..aafe569
--- /dev/null
@@ -0,0 +1,2238 @@
+/*
+** $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 supress 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 "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))
+
+/*******************************************************************************
+*                  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_STRUC_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_STRUC_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_STRUC_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_STRUC_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_STRUC_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_STRUC_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_STRUC_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_STRUC_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 */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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.
+*
+*/
+/*----------------------------------------------------------------------------*/
+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_STRUC_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_STRUC_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 = %d.\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 : PRIV_CUSTOM_BWCS_CMD : aucBTPParams[0] = %02x, aucBTPParams[1] = %02x, aucBTPParams[2] = %02x, aucBTPParams[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(INIT, INFO, ("CMD set_band=%u\n", pu4IntBuf[1]));
+        }
+        break;
+
+#if CFG_ENABLE_WIFI_DIRECT
+    case PRIV_CMD_P2P_MODE:
+        {
+            PARAM_CUSTOM_P2P_SET_STRUC_T rSetP2P;
+            WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS;
+
+            rSetP2P.u4Enable = pu4IntBuf[1];
+            rSetP2P.u4Mode = pu4IntBuf[2];
+
+            if(!rSetP2P.u4Enable) {
+                p2pNetUnregister(prGlueInfo, TRUE);
+            }
+
+            rWlanStatus = kalIoctl(prGlueInfo,
+                                wlanoidSetP2pMode,
+                                (PVOID)&rSetP2P, /* pu4IntBuf[0] is used as input SubCmd */
+                                sizeof(PARAM_CUSTOM_P2P_SET_STRUC_T),
+                                FALSE,
+                                FALSE,
+                                TRUE,
+                                FALSE,
+                                &u4BufLen);
+
+            if(rSetP2P.u4Enable) {
+                p2pNetRegister(prGlueInfo, TRUE);
+            }
+
+
+        }
+        break;
+#endif
+
+    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.
+*
+*/
+/*----------------------------------------------------------------------------*/
+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;
+    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->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(INIT, 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;
+            RF_CHANNEL_INFO_T aucChannelList[50];
+
+            kalGetChannelList(prGlueInfo, BAND_NULL, ucMaxChannelNum, &NumOfChannel, aucChannelList);
+            if (NumOfChannel > 50)
+                NumOfChannel = 50;
+
+            if (kalIsAPmode(prGlueInfo)) {
+                for (i = 0; i < NumOfChannel; i++) {
+                    if ((aucChannelList[i].ucChannelNum <= 13) ||
+                        (aucChannelList[i].ucChannelNum == 36 || aucChannelList[i].ucChannelNum == 40 ||
+                        aucChannelList[i].ucChannelNum == 44 || aucChannelList[i].ucChannelNum == 48)) {
+                        ch[j] = (INT_32)aucChannelList[i].ucChannelNum;
+                        j++;
+                    }
+                }
+            }
+            else {
+                for (j = 0; j < NumOfChannel; j++) {
+                    ch[j] = (INT_32)aucChannelList[j].ucChannelNum;
+                }
+            }
+
+            prIwReqData->data.length = j;
+            if (copy_to_user(prIwReqData->data.pointer, ch, NumOfChannel*sizeof(INT_32))) {
+                 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.
+*
+*/
+/*----------------------------------------------------------------------------*/
+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
+        printk("Tx power num = %d\n", prIwReqData->data.length);
+
+        printk("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.
+*
+*/
+/*----------------------------------------------------------------------------*/
+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];
+
+            kalGetChannelList(prGlueInfo, BAND_NULL, ucMaxChannelNum, &NumOfChannel, aucChannelList);
+            if (NumOfChannel > 50)
+                NumOfChannel = 50;
+
+            for (i = 0; i < NumOfChannel; i++) {
+                ch[i] = (INT_32)aucChannelList[i].ucChannelNum;
+            }
+
+            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.
+*
+*/
+/*----------------------------------------------------------------------------*/
+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
+    printk(KERN_INFO DRV_NAME"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(%ld)\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.
+*
+*/
+/*----------------------------------------------------------------------------*/
+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
+    printk(KERN_INFO DRV_NAME"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
+        printk(KERN_NOTICE "\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;
+        }
+        else {
+            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;
+        }
+        break;
+
+    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;
+        break;
+    default:
+        DBGLOG(REQ, WARN, ("get struct cmd:0x%lx\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
+    printk(KERN_INFO DRV_NAME"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
+    printk(KERN_INFO DRV_NAME"priv_set_ndis(): %s\n",
+        prWlanReqEntry->pucOidName
+        );
+#endif
+
+    if (prWlanReqEntry->fgSetBufLenChecking) {
+        if (prNdisReq->inNdisOidlength != prWlanReqEntry->u4InfoBufLen) {
+            DBGLOG(REQ, WARN, ("Set %s: Invalid length (current=%ld, needed=%ld)\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
+    printk(KERN_INFO DRV_NAME"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
+    printk(KERN_INFO DRV_NAME"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 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;
+}
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/hif/sdio/arm.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/hif/sdio/arm.c
new file mode 100755 (executable)
index 0000000..4322fa3
--- /dev/null
@@ -0,0 +1,33 @@
+/******************************************************************************
+*[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/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/hif/sdio/include/hif.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/hif/sdio/include/hif.h
new file mode 100755 (executable)
index 0000000..23eac46
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+** $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
+
+
+#if MTK_WCN_HIF_SDIO
+#include "hif_sdio.h"
+#endif
+
+/*******************************************************************************
+*                         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 SDIO_X86_WORKAROUND_WRITE_MCR   0x00C4
+
+/*******************************************************************************
+*                             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_INFO_T {
+#if MTK_WCN_HIF_SDIO 
+    MTK_WCN_HIF_SDIO_CLTCTX cltCtx;
+    const MTK_WCN_HIF_SDIO_FUNCINFO *prFuncInfo;
+#else
+    struct sdio_func       *func;
+#endif
+    BOOLEAN                 fgIntReadClear;
+    BOOLEAN                 fgMbxReadClear;
+} GL_HIF_INFO_T, *P_GL_HIF_INFO_T;
+
+
+#if CFG_DBG_GPIO_PINS
+
+extern void
+mtk_wcn_stp_debug_gpio_assert(UINT_32 dwIndex, UINT_32 dwMethod);
+
+
+/* Platform DEPENDENT configurations: MT6516 GPIO pin name */
+#define GPIO_6516(x) (GPIO##x)
+#define GPIO_PLATFORM(x) GPIO_6516(x)
+
+/* Platform independent configurations */
+#define DBG_TIE_DIR 0x40000000UL
+#define DBG_LOW 0x0UL
+#define DBG_HIGH 0x1UL
+#define DBG_TIE_LOW (DBG_TIE_DIR | DBG_LOW)
+#define DBG_TIE_HIGH (DBG_TIE_DIR | DBG_HIGH)
+
+#define DBG_TOGGLE(x) (0x80000000UL | x)
+#define DBG_TOGGLE_NUM(x) (x & 0xFFF)
+#define GPIO_INVALID 0xFFFF
+
+typedef enum {
+    IDX_ERR = 0,
+    IDX_TX_THREAD,
+    IDX_TX_REQ,
+    IDX_TX_PORT_WRITE,
+    IDX_STP_MTX_BT,
+    IDX_STP_MTX_FM, /* 5 */
+    IDX_STP_MTX_GPS,
+    IDX_STP_MTX_WIFI,
+    IDX_STP_MTX_WMT,
+    IDX_LOOP_CNT,
+    IDX_NO_BUF, /*10 */
+    IDX_BT_TX,
+    IDX_BT_RX,
+    IDX_GPS_RX,
+    IDX_GPS_2,
+    IDX_GPS_3,
+    IDX_GPS_TX,
+    IDX_STP_MAX
+} DBG_PIN;
+
+#define DBG_MTX_OFFSET (IDX_STP_MTX_BT) /* index of mutex0 */
+#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
+********************************************************************************
+*/
+
+WLAN_STATUS
+glRegisterBus(
+    probe_card pfProbe,
+    remove_card pfRemove
+    );
+
+VOID
+glUnregisterBus(
+    remove_card pfRemove
+    );
+
+VOID
+glSetHifInfo (
+    P_GLUE_INFO_T prGlueInfo,
+    UINT_32 u4Cookie
+    );
+
+VOID
+glClearHifInfo (
+    P_GLUE_INFO_T prGlueInfo
+    );
+
+BOOL
+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
+    );
+
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+#endif /* _HIF_H */
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/hif/sdio/include/hif_sdio.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/hif/sdio/include/hif_sdio.h
new file mode 100755 (executable)
index 0000000..9fac1e0
--- /dev/null
@@ -0,0 +1,290 @@
+/*
+** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/hif/sdio/include/hif_sdio.h#2 $
+*/
+
+/*! \file   "hif_sdio.h"
+    \brief
+
+
+*/
+
+/*
+** $Log: $
+ *
+ * 06 13 2012 yuche.tsai
+ * NULL
+ * Update maintrunk driver.
+ * Add support for driver compose assoc request frame.
+ *
+ * 05 02 2012 terry.wu
+ * NULL
+ * Fix build error if HAVE_AEE_FEATURE = n
+ *
+ * 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.
+ *
+ * 08 18 2010 jeffrey.chang
+ * NULL
+ * support multi-function sdio
+ *
+ * 07 25 2010 george.kuo
+ *
+ * Move hif_sdio driver to linux directory.
+ *
+ * 07 23 2010 george.kuo
+ *
+ * Add MT6620 driver source tree
+ * , including char device driver (wmt, bt, gps), stp driver, interface driver (tty ldisc and hif_sdio), and bt hci driver.
+**
+**
+*/
+
+#ifndef _HIF_SDIO_H
+#define _HIF_SDIO_H
+/*******************************************************************************
+*                         C O M P I L E R   F L A G S
+********************************************************************************
+*/
+#define HIF_SDIO_DEBUG  (0) /* 0:trun off debug msg and assert, 1:trun off debug msg and assert */
+
+/*******************************************************************************
+*                    E X T E R N A L   R E F E R E N C E S
+********************************************************************************
+*/
+#include "mtk_porting.h"
+
+/*******************************************************************************
+*                              C O N S T A N T S
+********************************************************************************
+*/
+#define CFG_CLIENT_COUNT  (9)
+
+#define HIF_DEFAULT_BLK_SIZE  (256)
+#define HIF_DEFAULT_VENDOR    (0x037A)
+
+#define HIF_SDIO_LOG_LOUD    4
+#define HIF_SDIO_LOG_DBG     3
+#define HIF_SDIO_LOG_INFO    2
+#define HIF_SDIO_LOG_WARN    1
+#define HIF_SDIO_LOG_ERR     0
+
+
+/*******************************************************************************
+*                             D A T A   T Y P E S
+********************************************************************************
+*/
+
+/* Function info provided by client driver */
+typedef struct _MTK_WCN_HIF_SDIO_FUNCINFO MTK_WCN_HIF_SDIO_FUNCINFO;
+
+/* Client context provided by hif_sdio driver for the following function call */
+typedef UINT32 MTK_WCN_HIF_SDIO_CLTCTX;
+
+/* Callback functions provided by client driver */
+typedef INT32 (*MTK_WCN_HIF_SDIO_PROBE)(MTK_WCN_HIF_SDIO_CLTCTX, const MTK_WCN_HIF_SDIO_FUNCINFO *);
+typedef INT32 (*MTK_WCN_HIF_SDIO_REMOVE)(MTK_WCN_HIF_SDIO_CLTCTX);
+typedef INT32 (*MTK_WCN_HIF_SDIO_IRQ)(MTK_WCN_HIF_SDIO_CLTCTX);
+
+/* Function info provided by client driver */
+struct _MTK_WCN_HIF_SDIO_FUNCINFO {
+    UINT16 manf_id;    /* TPLMID_MANF: manufacturer ID */
+    UINT16 card_id;    /* TPLMID_CARD: card ID */
+    UINT16 func_num;    /* Function Number */
+    UINT16 blk_sz;    /* Function block size */
+};
+
+/* Client info provided by client driver */
+typedef struct _MTK_WCN_HIF_SDIO_CLTINFO {
+    const MTK_WCN_HIF_SDIO_FUNCINFO *func_tbl; /* supported function info table */
+    UINT32 func_tbl_size; /* supported function table info element number */
+    MTK_WCN_HIF_SDIO_PROBE hif_clt_probe; /* callback function for probing */
+    MTK_WCN_HIF_SDIO_REMOVE hif_clt_remove; /* callback function for removing */
+    MTK_WCN_HIF_SDIO_IRQ hif_clt_irq; /* callback function for interrupt handling */
+} MTK_WCN_HIF_SDIO_CLTINFO;
+
+/* function info provided by registed function */
+typedef struct _MTK_WCN_HIF_SDIO_REGISTINFO {
+    const MTK_WCN_HIF_SDIO_CLTINFO *sdio_cltinfo; /* client's MTK_WCN_HIF_SDIO_CLTINFO pointer */
+    const MTK_WCN_HIF_SDIO_FUNCINFO *func_info; /* supported function info pointer */
+} MTK_WCN_HIF_SDIO_REGISTINFO;
+
+/* Card info provided by probed function */
+typedef struct _MTK_WCN_HIF_SDIO_PROBEINFO {
+    struct sdio_func* func;  /* probed sdio function pointer */
+    void* private_data_p;  /* clt's private data pointer */
+    MTK_WCN_BOOL on_by_wmt;   /* TRUE: on by wmt, FALSE: not on by wmt */
+    /* added for sdio irq sync and mmc single_irq workaround */
+    MTK_WCN_BOOL sdio_irq_enabled; /* TRUE: can handle sdio irq; FALSE: no sdio irq handling */
+    INT8 clt_idx;   /* registered function table info element number (initial value is -1) */
+} MTK_WCN_HIF_SDIO_PROBEINFO;
+
+
+/* work queue info needed by worker */
+typedef struct _MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO {
+    struct work_struct probe_work;   /* work queue structure */
+    MTK_WCN_HIF_SDIO_REGISTINFO *registinfo_p;  /* MTK_WCN_HIF_SDIO_REGISTINFO pointer of the client */
+    INT8 probe_idx;   /* probed function table info element number (initial value is -1) */
+} MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO;
+
+/* error code returned by hif_sdio driver (use NEGATIVE number) */
+typedef enum {
+    HIF_SDIO_ERR_SUCCESS = 0,
+    HIF_SDIO_ERR_FAIL = HIF_SDIO_ERR_SUCCESS - 1, /* generic error */
+    HIF_SDIO_ERR_INVALID_PARAM = HIF_SDIO_ERR_FAIL - 1,
+    HIF_SDIO_ERR_DUPLICATED = HIF_SDIO_ERR_INVALID_PARAM - 1,
+    HIF_SDIO_ERR_UNSUP_MANF_ID = HIF_SDIO_ERR_DUPLICATED - 1,
+    HIF_SDIO_ERR_UNSUP_CARD_ID = HIF_SDIO_ERR_UNSUP_MANF_ID - 1,
+    HIF_SDIO_ERR_INVALID_FUNC_NUM = HIF_SDIO_ERR_UNSUP_CARD_ID - 1,
+    HIF_SDIO_ERR_INVALID_BLK_SZ = HIF_SDIO_ERR_INVALID_FUNC_NUM - 1,
+    HIF_SDIO_ERR_NOT_PROBED = HIF_SDIO_ERR_INVALID_BLK_SZ - 1,
+    HIF_SDIO_ERR_ALRDY_ON = HIF_SDIO_ERR_NOT_PROBED -1,
+    HIF_SDIO_ERR_ALRDY_OFF = HIF_SDIO_ERR_ALRDY_ON -1,
+    HIF_SDIO_ERR_CLT_NOT_REG = HIF_SDIO_ERR_ALRDY_OFF - 1,
+} MTK_WCN_HIF_SDIO_ERR ;
+
+
+/*******************************************************************************
+*                            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
+********************************************************************************
+*/
+
+/*!
+ * \brief A macro used to describe an SDIO function
+ *
+ * Fill an MTK_WCN_HIF_SDIO_FUNCINFO structure with function-specific information
+ *
+ * \param manf      the 16 bit manufacturer id
+ * \param card      the 16 bit card id
+ * \param func      the 16 bit function number
+ * \param b_sz    the 16 bit function block size
+ */
+#define MTK_WCN_HIF_SDIO_FUNC(manf, card, func, b_sz) \
+       .manf_id = (manf), .card_id = (card), .func_num = (func), .blk_sz = (b_sz)
+
+#define HIF_SDIO_LOUD_FUNC(fmt, arg...)   if (gHifSdioDbgLvl >= HIF_SDIO_LOG_LOUD) { printk(KERN_INFO SDIO_TAG"[L]%s:"  fmt, __FUNCTION__ ,##arg);}
+#define HIF_SDIO_DBG_FUNC(fmt, arg...)    if (gHifSdioDbgLvl >= HIF_SDIO_LOG_DBG) { printk(KERN_INFO SDIO_TAG"[D]%s:"  fmt, __FUNCTION__ ,##arg);}
+#define HIF_SDIO_INFO_FUNC(fmt, arg...)   if (gHifSdioDbgLvl >= HIF_SDIO_LOG_INFO) { printk(KERN_INFO SDIO_TAG"[I]%s:"  fmt, __FUNCTION__ ,##arg);}
+#define HIF_SDIO_WARN_FUNC(fmt, arg...)   if (gHifSdioDbgLvl >= HIF_SDIO_LOG_WARN) { printk(KERN_WARNING SDIO_TAG"[W]%s(%d):"  fmt, __FUNCTION__ , __LINE__, ##arg);}
+#define HIF_SDIO_ERR_FUNC(fmt, arg...)    if (gHifSdioDbgLvl >= HIF_SDIO_LOG_ERR) { printk(KERN_WARNING SDIO_TAG"[E]%s(%d):"  fmt, __FUNCTION__ , __LINE__, ##arg);}
+
+
+/*!
+ * \brief ASSERT function definition.
+ *
+ */
+#if HIF_SDIO_DEBUG
+#define HIF_SDIO_ASSERT(expr)    if ( !(expr) ) { \
+
+                            printk("assertion failed! %s[%d]: %s\n",\
+                                __FUNCTION__, __LINE__, #expr); \
+                            BUG_ON( !(expr) );\
+                        }
+#else
+#define HIF_SDIO_ASSERT(expr)    do {} while(0)
+#endif
+
+/*******************************************************************************
+*                   F U N C T I O N   D E C L A R A T I O N S
+********************************************************************************
+*/
+
+/*!
+ * \brief MTK hif sdio client registration function
+ *
+ * Client uses this function to do hif sdio registration
+ *
+ * \param pinfo     a pointer of client's information
+ *
+ * \retval 0    register successfully
+ * \retval < 0  error code
+ */
+extern INT32 mtk_wcn_hif_sdio_client_reg (
+    const MTK_WCN_HIF_SDIO_CLTINFO *pinfo
+    );
+
+extern INT32 mtk_wcn_hif_sdio_client_unreg (
+    const MTK_WCN_HIF_SDIO_CLTINFO *pinfo
+    );
+
+extern INT32 mtk_wcn_hif_sdio_readb (
+    MTK_WCN_HIF_SDIO_CLTCTX ctx,
+    UINT32 offset,
+    PUINT8 pvb
+    );
+
+extern INT32 mtk_wcn_hif_sdio_writeb (
+    MTK_WCN_HIF_SDIO_CLTCTX ctx,
+    UINT32 offset,
+    UINT8 vb
+    );
+
+extern INT32 mtk_wcn_hif_sdio_readl (
+    MTK_WCN_HIF_SDIO_CLTCTX ctx,
+    UINT32 offset,
+    PUINT32 pvl
+    );
+
+extern INT32 mtk_wcn_hif_sdio_writel (
+    MTK_WCN_HIF_SDIO_CLTCTX ctx,
+    UINT32 offset,
+    UINT32 vl
+    );
+
+extern INT32 mtk_wcn_hif_sdio_read_buf (
+    MTK_WCN_HIF_SDIO_CLTCTX ctx,
+    UINT32 offset,
+    PUINT32 pbuf,
+    UINT32 len
+    );
+
+extern INT32 mtk_wcn_hif_sdio_write_buf (
+    MTK_WCN_HIF_SDIO_CLTCTX ctx,
+    UINT32 offset,
+    PUINT32 pbuf,
+    UINT32 len
+    );
+
+extern void mtk_wcn_hif_sdio_set_drvdata(
+    MTK_WCN_HIF_SDIO_CLTCTX ctx,
+    void* private_data_p
+    );
+
+extern void* mtk_wcn_hif_sdio_get_drvdata(
+    MTK_WCN_HIF_SDIO_CLTCTX ctx
+    );
+
+extern void mtk_wcn_hif_sdio_get_dev(
+    MTK_WCN_HIF_SDIO_CLTCTX ctx,
+    struct device **dev
+    );
+extern void mtk_wcn_hif_sdio_enable_irq(
+    MTK_WCN_HIF_SDIO_CLTCTX ctx,
+    MTK_WCN_BOOL enable
+    );
+
+
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+#endif /* _HIF_SDIO_H */
+
+
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/hif/sdio/include/mtk_porting.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/hif/sdio/include/mtk_porting.h
new file mode 100755 (executable)
index 0000000..37f96be
--- /dev/null
@@ -0,0 +1,52 @@
+/* porting layer */
+/* Android */
+
+#ifndef _MTK_PORTING_H_
+#define _MTK_PORTING_H_
+
+#include <linux/kernel.h> /* include stddef.h for NULL */
+
+/* Type definition for signed integers */
+typedef signed char INT8, *PINT8;
+typedef signed short INT16, *PINT16;
+typedef signed int INT32, *PINT32;
+
+/* Type definition for unsigned integers */
+typedef unsigned char UINT8, *PUINT8;
+typedef unsigned short UINT16, *PUINT16;
+typedef unsigned int UINT32, *PUINT32;
+
+//typedef void VOID, *PVOID;
+
+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 INT32 (*MUTEX_DESTROY)(MTK_WCN_MUTEX mtx);
+typedef INT32 (*MUTEX_LOCK)(MTK_WCN_MUTEX mtx);
+typedef INT32 (*MUTEX_UNLOCK)(MTK_WCN_MUTEX mtx, unsigned long flags);
+/* debug */
+typedef INT32 (*DBG_PRINT)(const char *str, ...);
+typedef INT32 (*DBG_ASSERT)(INT32 expr, const char *file, INT32 line);
+/* timer */
+typedef void (*MTK_WCN_TIMER_CB)(void);
+typedef MTK_WCN_TIMER (*TIMER_CREATE)(const char * const name);
+typedef INT32 (*TIMER_DESTROY)(MTK_WCN_TIMER tmr);
+typedef INT32 (*TIMER_START)(MTK_WCN_TIMER tmr, UINT32 timeout, MTK_WCN_TIMER_CB tmr_cb, void *param);
+typedef INT32 (*TIMER_STOP)(MTK_WCN_TIMER tmr);
+/* kernel lib */
+typedef void* (*SYS_MEMCPY)(void *dest, const void *src, UINT32 n);
+typedef void* (*SYS_MEMSET)(void *s, INT32 c, UINT32 n);
+typedef INT32 (*SYS_SPRINTF)(char *str, const char *format, ...);
+
+#endif /* _MTK_PORTING_H_ */
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/hif/sdio/sdio.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/hif/sdio/sdio.c
new file mode 100755 (executable)
index 0000000..1527789
--- /dev/null
@@ -0,0 +1,1329 @@
+/******************************************************************************
+*[File]             sdio.c
+*[Version]          v1.0
+*[Revision Date]    2010-03-01
+*[Author]
+*[Description]
+*    The program provides SDIO HIF driver
+*[Copyright]
+*    Copyright (C) 2010 MediaTek Incorporation. All Rights Reserved.
+******************************************************************************/
+
+
+
+/*
+** $Log: sdio.c $
+ *
+ * 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 settting 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 "gl_os.h"
+
+#if MTK_WCN_HIF_SDIO
+#include "hif_sdio.h"
+#else
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/sdio_func.h> /* sdio_readl(), etc */
+#include <linux/mmc/sdio_ids.h>
+#endif
+
+#include <linux/mm.h>
+//#ifndef CONFIG_X86  modify by Nicolas Luo
+#ifdef CONFIG_ARM
+#include <asm/memory.h>
+#endif
+
+
+#if defined(MT6620)
+    #include "mt6620_reg.h"
+#elif defined(MT5931)
+    #include "mt5931_reg.h"
+#elif defined(MT6628)
+    #include "mt6628_reg.h"
+#endif
+
+#if CFG_DBG_GPIO_PINS/* FIXME: move to platform or custom header */
+#include <mach/mt6516_gpio.h>
+#endif
+
+/*******************************************************************************
+*                              C O N S T A N T S
+********************************************************************************
+*/
+
+#define HIF_SDIO_ERR_TITLE_STR              "["CHIP_NAME"] SDIO Access Error!"
+#define HIF_SDIO_ERR_DESC_STR               "**SDIO Access Error**\n"
+
+#if MTK_WCN_HIF_SDIO
+
+
+/*
+ * function prototypes
+ *
+ */
+
+static INT32
+mtk_sdio_probe(MTK_WCN_HIF_SDIO_CLTCTX, const MTK_WCN_HIF_SDIO_FUNCINFO *);
+
+static INT32
+mtk_sdio_remove(MTK_WCN_HIF_SDIO_CLTCTX);
+static INT32 mtk_sdio_interrupt(MTK_WCN_HIF_SDIO_CLTCTX);
+
+/*
+ * sdio function info table
+ */
+
+static MTK_WCN_HIF_SDIO_FUNCINFO funcInfo[] = {
+#if defined(MT6620)
+    { MTK_WCN_HIF_SDIO_FUNC(0x037a, 0x020a, 0x1, 512) },
+    { MTK_WCN_HIF_SDIO_FUNC(0x037a, 0x020c, 0x2, 512) },
+    { MTK_WCN_HIF_SDIO_FUNC(0x037a, 0x018a, 0x1, 512) },
+    { MTK_WCN_HIF_SDIO_FUNC(0x037a, 0x018c, 0x2, 512) },
+#elif defined(MT5931)
+    { MTK_WCN_HIF_SDIO_FUNC(0x037a, 0x5931, 0x1, 512) },
+#elif defined(MT6628)
+    { MTK_WCN_HIF_SDIO_FUNC(0x037a, 0x6628, 0x1, 512) },
+#endif
+};
+
+
+static MTK_WCN_HIF_SDIO_CLTINFO cltInfo = {
+    .func_tbl = funcInfo,
+    .func_tbl_size = sizeof(funcInfo)/sizeof(MTK_WCN_HIF_SDIO_FUNCINFO),
+    .hif_clt_probe = mtk_sdio_probe,
+    .hif_clt_remove = mtk_sdio_remove,
+    .hif_clt_irq = mtk_sdio_interrupt,
+};
+
+#else
+
+static const struct sdio_device_id mtk_sdio_ids[] = {
+#if defined(MT6620)
+       { SDIO_DEVICE(0x037a, 0x020a) }, /* Not an SDIO standard class device */
+       { SDIO_DEVICE(0x037a, 0x020b) }, /* Not an SDIO standard class device */
+       { SDIO_DEVICE(0x037a, 0x020c) }, /* Not an SDIO standard class device */
+#elif defined(MT5931)
+       { SDIO_DEVICE(0x037a, 0x5931) }, /* Not an SDIO standard class device */
+#elif defined(MT6628)
+       { SDIO_DEVICE(0x037a, 0x6628) }, /* Not an SDIO standard class device */
+#endif
+       { /* end: all zeroes */ },
+};
+
+MODULE_DEVICE_TABLE(sdio, mtk_sdio_ids);
+
+#endif
+
+/*******************************************************************************
+*                             D A T A   T Y P E S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+*                            P U B L I C   D A T A
+********************************************************************************
+*/
+extern KAL_WAKE_LOCK_T isr_wakelock;
+
+/*******************************************************************************
+*                           P R I V A T E   D A T A
+********************************************************************************
+*/
+static probe_card pfWlanProbe = NULL;
+static remove_card pfWlanRemove = NULL;
+
+
+#if (MTK_WCN_HIF_SDIO == 0)
+static struct sdio_driver mtk_sdio_driver = {
+       .name           = "wlan", /* "MTK SDIO WLAN Driver" */
+       .id_table       = mtk_sdio_ids,
+       .probe          = NULL,
+       .remove         = NULL,
+};
+#endif
+
+
+#if CFG_DBG_GPIO_PINS
+
+/* debug pins */
+UINT_32 dbgPinSTP[] = {
+    GPIO_PLATFORM(33)/* CMFLASH, IDX_ERR J613 */
+    , GPIO_PLATFORM(62)/* EINT3, IDX_TX_THREAD */
+    , GPIO_PLATFORM(80)/* SPI_CS_N, IDX_TX_REQ J613 */
+    , GPIO_PLATFORM(81)/* SPI_SCK, IDX_TX_PORT_WRITE J613 */
+    , GPIO_PLATFORM(17) /* CMRST, IDX_STP_MTX_BT J618 */
+    , GPIO_PLATFORM(18) /* CMPDN, IDX_STP_MTX_FM J613 */
+    , GPIO_PLATFORM(19) /* CMVREF,IDX_STP_MTX_GPS J613 */
+    , GPIO_INVALID /* REMOVED, IDX_STP_MTX_WIFI */
+    , GPIO_INVALID /* REMOVED, IDX_STP_MTX_WMT */
+    , GPIO_PLATFORM(135) /* SCL2, IDX_LOOP_CNT  J616 */
+    , GPIO_PLATFORM(136) /* SDA2, IDX_NO_BUF J616 */
+    , GPIO_PLATFORM(30) /* CAM_MECHSH0, IDX_BT_TX, J613 low-active */
+    , GPIO_PLATFORM(31) /* CAM_MECHSH1, IDX_BT_RX, J613 low-active */
+    , GPIO_PLATFORM(124) /* GPS_PWR_EN, ThreadDSPIn [GPS] */
+    , GPIO_PLATFORM(125) /* GPS_SYNC, mtk_sys_msg_recv [GPS] */
+    , GPIO_PLATFORM(21) /* GPS_EINT8, dump_nmea_data [GPS] */
+    , GPIO_PLATFORM(29) /* CAM_STROBE, IDX_GPS_TX, J613 low-active */
+    , GPIO_PLATFORM(20) /*CMHREF, J613 UNUSED */
+//    , GPIO_6516(64) /* EINT5, REMOVED!!! for MT6620-Wi-Fi Int */
+//    , GPIO_6516(122) /* BT_PWR_EN, REMOVED!!! for MT6620-PMU_EN */
+//    , GPIO_6516(123) /* BT_RESET, REMOVED!!! for MT6620-RST */
+};
+#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
+********************************************************************************
+*/
+#if CFG_DBG_GPIO_PINS
+void debug_gpio_init(void)
+{
+    int i;
+
+    for (i = 0; i < sizeof(dbgPinSTP)/sizeof(dbgPinSTP[0]); ++i) {
+        if (GPIO_INVALID == dbgPinSTP[i]) {
+            continue;
+        }
+        //printk(KERN_INFO "[%s] %ld \n", __FUNCTION__, dbgPinSTP[i]);
+        mt_set_gpio_pull_enable(dbgPinSTP[i], 0); /* disable pull */
+        mt_set_gpio_dir(dbgPinSTP[i], GPIO_DIR_OUT); /* set output */
+        mt_set_gpio_mode(dbgPinSTP[i], GPIO_MODE_00); /* set gpio mode */
+
+        /* toggle twice to check if ok: */
+        mt_set_gpio_out(dbgPinSTP[i], GPIO_OUT_ZERO); /* tie low */
+        mt_set_gpio_out(dbgPinSTP[i], GPIO_OUT_ONE); /* tie high*/
+        mt_set_gpio_out(dbgPinSTP[i], GPIO_OUT_ZERO); /* tie low */
+        mt_set_gpio_out(dbgPinSTP[i], GPIO_OUT_ONE); /* tie high*/
+    }
+    //printk(KERN_INFO "[%s] initialization ok \n", __FUNCTION__);
+}
+
+void debug_gpio_deinit(void)
+{
+    int i;
+    for (i = 0; i < sizeof(dbgPinSTP)/sizeof(dbgPinSTP[0]); ++i) {
+        if (GPIO_INVALID == dbgPinSTP[i]) {
+            continue;
+        }
+        //printk(KERN_INFO "[%s] %ld \n", __FUNCTION__, dbgPinSTP[i]);
+        mt_set_gpio_dir(dbgPinSTP[i], GPIO_DIR_IN);
+    }
+
+    //printk(KERN_INFO "[%s] k\n", __FUNCTION__);
+}
+
+void mtk_wcn_stp_debug_gpio_assert(UINT_32 dwIndex, UINT_32 dwMethod)
+{
+    unsigned int i;
+
+    if (dwIndex >= (sizeof(dbgPinSTP)/sizeof(dbgPinSTP[0]))) {
+        //printk(KERN_INFO "[%s] invalid dwIndex(%ld) \n", __FUNCTION__, dwIndex);
+        return;
+    }
+
+    if (dwIndex > IDX_STP_MAX) {
+        //printk(KERN_INFO "[%s] dwIndex(%ld) > IDX_STP_MAX(%d) \n", __FUNCTION__, dwIndex, IDX_STP_MAX);
+    }
+
+    if (GPIO_INVALID == dbgPinSTP[dwIndex]) {
+        return;
+    }
+
+    if (dwMethod & DBG_TIE_DIR) {
+        if (dwMethod & DBG_HIGH) {
+            mt_set_gpio_out(dbgPinSTP[dwIndex], GPIO_OUT_ONE);
+        }
+        else {
+            mt_set_gpio_out(dbgPinSTP[dwIndex], GPIO_OUT_ZERO);
+        }
+        return;
+    }
+
+    if (dwMethod & DBG_TOGGLE(0)) {
+        for (i = 0; i < DBG_TOGGLE_NUM(dwMethod); ++i) {
+            mt_set_gpio_out(dbgPinSTP[dwIndex], GPIO_OUT_ZERO);
+            mt_set_gpio_out(dbgPinSTP[dwIndex], GPIO_OUT_ONE);
+        }
+        return;
+    }
+
+    return;
+}
+#endif
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief This function is a SDIO interrupt callback function
+*
+* \param[in] func  pointer to SDIO handle
+*
+* \return void
+*/
+/*----------------------------------------------------------------------------*/
+
+#if MTK_WCN_HIF_SDIO
+
+static INT32 mtk_sdio_interrupt(MTK_WCN_HIF_SDIO_CLTCTX cltCtx)
+{
+    P_GLUE_INFO_T prGlueInfo = NULL;
+    INT32 ret = 0;
+
+    prGlueInfo = mtk_wcn_hif_sdio_get_drvdata(cltCtx);
+
+    ASSERT(prGlueInfo);
+
+    if (!prGlueInfo) {
+        //printk(KERN_INFO DRV_NAME"No glue info in mtk_sdio_interrupt()\n");
+        return (-HIF_SDIO_ERR_FAIL);
+    }
+
+    if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) {
+        //printk(KERN_INFO DRV_NAME"GLUE_FLAG_HALT skip INT\n");
+        ret = mtk_wcn_hif_sdio_writel(cltCtx, MCR_WHLPCR, WHLPCR_INT_EN_CLR);
+        return ret;
+    }
+     /*WCNCR 00002676*/
+    KAL_WAKE_UNLOCK(NULL, &isr_wakelock);
+    KAL_WAKE_LOCK_TIMEOUT(NULL, &isr_wakelock, KAL_HZ/10);
+    ret = mtk_wcn_hif_sdio_writel(cltCtx, MCR_WHLPCR, WHLPCR_INT_EN_CLR);
+
+    set_bit (GLUE_FLAG_INT_BIT, &prGlueInfo->u4Flag);
+
+    /* when we got sdio interrupt, we wake up the tx servie thread*/
+    wake_up_interruptible(&prGlueInfo->waitq);
+
+    return ret;
+}
+
+#else
+
+static unsigned int in_interrupt = 0;
+
+static void mtk_sdio_interrupt(struct sdio_func *func)
+{
+    P_GLUE_INFO_T prGlueInfo = NULL;
+
+    int ret = 0;
+
+    prGlueInfo = sdio_get_drvdata(func);
+    ASSERT(prGlueInfo);
+
+    if (!prGlueInfo) {
+        //printk(KERN_INFO DRV_NAME"No glue info in mtk_sdio_interrupt()\n");
+        return;
+    }
+
+    if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) {
+        sdio_writel(prGlueInfo->rHifInfo.func, WHLPCR_INT_EN_CLR, MCR_WHLPCR, &ret);
+        //printk(KERN_INFO DRV_NAME"GLUE_FLAG_HALT skip INT\n");
+        return;
+    }
+
+    sdio_writel(prGlueInfo->rHifInfo.func, WHLPCR_INT_EN_CLR, MCR_WHLPCR, &ret);
+
+    #if 0
+    wlanISR(prGlueInfo->prAdapter, TRUE);
+
+    if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) {
+        /* Should stop now... skip pending interrupt */
+        //printk(KERN_INFO DRV_NAME"ignore pending interrupt\n");
+    }
+    else {
+        wlanIST(prGlueInfo->prAdapter);
+    }
+    #endif
+
+    set_bit (GLUE_FLAG_INT_BIT, &prGlueInfo->u4Flag);
+
+    /* when we got sdio interrupt, we wake up the tx servie thread*/
+    wake_up_interruptible(&prGlueInfo->waitq);
+}
+#endif
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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 MTK_WCN_HIF_SDIO
+
+// FIXME: global variable
+static const MTK_WCN_HIF_SDIO_FUNCINFO *prFunc;
+
+
+static INT32
+mtk_sdio_probe(MTK_WCN_HIF_SDIO_CLTCTX cltCtx, const MTK_WCN_HIF_SDIO_FUNCINFO *prFuncInfo)
+{
+    INT32 ret = HIF_SDIO_ERR_SUCCESS;
+
+    prFunc = prFuncInfo;
+
+    if (pfWlanProbe((PVOID) &cltCtx) != WLAN_STATUS_SUCCESS) {
+        //printk(KERN_WARNING DRV_NAME"pfWlanProbe fail!call pfWlanRemove()\n");
+        pfWlanRemove();
+        ret = -(HIF_SDIO_ERR_FAIL);
+    } else {
+        //printk(KERN_INFO DRV_NAME"mtk_wifi_sdio_probe() done(%d)\n", ret);
+    }
+    return ret;
+}
+#else
+static int mtk_sdio_probe (
+    struct sdio_func *func,
+    const struct sdio_device_id *id
+    )
+{
+    int ret = 0;
+    int i = 0;
+
+    //printk(KERN_INFO DRV_NAME "mtk_sdio_probe()\n");
+
+    ASSERT(func);
+    ASSERT(id);
+
+    //printk(KERN_INFO DRV_NAME "Basic struct size checking...\n");
+    //printk(KERN_INFO DRV_NAME "sizeof(struct device) = %d\n", sizeof(struct device));
+    //printk(KERN_INFO DRV_NAME "sizeof(struct mmc_host) = %d\n", sizeof(struct mmc_host));
+    //printk(KERN_INFO DRV_NAME "sizeof(struct mmc_card) = %d\n", sizeof(struct mmc_card));
+    //printk(KERN_INFO DRV_NAME "sizeof(struct mmc_driver) = %d\n", sizeof(struct mmc_driver));
+    //printk(KERN_INFO DRV_NAME "sizeof(struct mmc_data) = %d\n", sizeof(struct mmc_data));
+    //printk(KERN_INFO DRV_NAME "sizeof(struct mmc_command) = %d\n", sizeof(struct mmc_command));
+    //printk(KERN_INFO DRV_NAME "sizeof(struct mmc_request) = %d\n", sizeof(struct mmc_request));
+    //printk(KERN_INFO DRV_NAME "sizeof(struct sdio_func) = %d\n", sizeof(struct sdio_func));
+
+    //printk(KERN_INFO DRV_NAME "Card information checking...\n");
+    //printk(KERN_INFO DRV_NAME "func = 0x%p\n", func);
+    //printk(KERN_INFO DRV_NAME "Number of info = %d:\n", func->card->num_info);
+
+    for (i = 0; i < func->card->num_info; i++) {
+        //printk(KERN_INFO DRV_NAME "info[%d]: %s\n", i, func->card->info[i]);
+    }
+
+    sdio_claim_host(func);
+    ret = sdio_enable_func(func);
+    sdio_release_host(func);
+
+    if (ret) {
+        //printk(KERN_INFO DRV_NAME"sdio_enable_func failed!\n");
+        goto out;
+    }
+    //printk(KERN_INFO DRV_NAME"sdio_enable_func done!\n");
+
+    if (pfWlanProbe((PVOID)func) != WLAN_STATUS_SUCCESS) {
+        //printk(KERN_WARNING DRV_NAME"pfWlanProbe fail!call pfWlanRemove()\n");
+        pfWlanRemove();
+        ret = -1;
+    }
+    else {
+#if CFG_DBG_GPIO_PINS
+    //printk(KERN_INFO "[%s] init debug gpio, 20100815 \n", __FUNCTION__);
+    /* Debug pins initialization */
+    debug_gpio_init();
+#endif
+    }
+
+out:
+    //printk(KERN_INFO DRV_NAME"mtk_sdio_probe() done(%d)\n", ret);
+    return ret;
+}
+#endif
+
+
+#if MTK_WCN_HIF_SDIO
+static INT32
+mtk_sdio_remove(MTK_WCN_HIF_SDIO_CLTCTX cltCtx)
+{
+    INT32 ret = HIF_SDIO_ERR_SUCCESS;
+    //printk(KERN_INFO DRV_NAME"pfWlanRemove done\n");
+    pfWlanRemove();
+
+    return ret;
+}
+#else
+static void
+mtk_sdio_remove (
+    struct sdio_func *func
+    )
+{
+    //printk(KERN_INFO DRV_NAME"mtk_sdio_remove()\n");
+
+#if CFG_DBG_GPIO_PINS
+    //printk(KERN_INFO "[%s] deinit debug gpio \n", __FUNCTION__);
+    debug_gpio_deinit();
+#endif
+
+    ASSERT(func);
+    //printk(KERN_INFO DRV_NAME"pfWlanRemove done\n");
+    pfWlanRemove();
+
+    sdio_claim_host(func);
+    sdio_disable_func(func);
+    //printk(KERN_INFO DRV_NAME"sdio_disable_func() done\n");
+    sdio_release_host(func);
+
+    //printk(KERN_INFO DRV_NAME"mtk_sdio_remove() done\n");
+}
+#endif
+
+#if (MTK_WCN_HIF_SDIO == 0)
+static int
+mtk_sdio_suspend (
+    struct device * pDev,
+    pm_message_t state
+    )
+{
+    //printk(KERN_INFO "mtk_sdio: mtk_sdio_suspend dev(0x%p)\n", pDev);
+    //printk(KERN_INFO "mtk_sdio: MediaTek SDIO WLAN driver\n");
+
+    return 0;
+}
+
+int mtk_sdio_resume (
+    struct device * pDev
+    )
+{
+    //printk(KERN_INFO "mtk_sdio: mtk_sdio_resume dev(0x%p)\n", pDev);
+
+    return 0;
+}
+#endif
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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 sdio bus
+*/
+/*----------------------------------------------------------------------------*/
+WLAN_STATUS
+glRegisterBus (
+    probe_card pfProbe,
+    remove_card pfRemove
+    )
+{
+    int ret = 0;
+
+    ASSERT(pfProbe);
+    ASSERT(pfRemove);
+
+    //printk(KERN_INFO "mtk_sdio: MediaTek SDIO WLAN driver\n");
+    //printk(KERN_INFO "mtk_sdio: Copyright MediaTek Inc.\n");
+
+    pfWlanProbe = pfProbe;
+    pfWlanRemove = pfRemove;
+
+#if MTK_WCN_HIF_SDIO
+    /* register MTK sdio client */
+    ret = ((mtk_wcn_hif_sdio_client_reg(&cltInfo) == HIF_SDIO_ERR_SUCCESS) ? WLAN_STATUS_SUCCESS : WLAN_STATUS_FAILURE);
+#else
+    mtk_sdio_driver.probe = mtk_sdio_probe;
+    mtk_sdio_driver.remove = mtk_sdio_remove;
+
+    mtk_sdio_driver.drv.suspend = mtk_sdio_suspend;
+    mtk_sdio_driver.drv.resume = mtk_sdio_resume;
+
+    ret = (sdio_register_driver(&mtk_sdio_driver) == 0) ? WLAN_STATUS_SUCCESS : WLAN_STATUS_FAILURE;
+#endif
+
+    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 MTK_WCN_HIF_SDIO
+    /* unregister MTK sdio client */
+    mtk_wcn_hif_sdio_client_unreg(&cltInfo);
+#else
+    sdio_unregister_driver(&mtk_sdio_driver);
+#endif
+
+    return;
+} /* end of glUnregisterBus() */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief This function stores hif related info, which is initialized before.
+*
+* \param[in] prGlueInfo Pointer to glue info structure
+* \param[in] u4Cookie   Pointer to UINT_32 memory base variable for _HIF_HPI
+*
+* \return (none)
+*/
+/*----------------------------------------------------------------------------*/
+VOID
+glSetHifInfo (
+    P_GLUE_INFO_T prGlueInfo,
+    UINT_32 u4Cookie
+    )
+{
+    P_GL_HIF_INFO_T prHif = NULL;
+
+    prHif = &prGlueInfo->rHifInfo;
+
+#if MTK_WCN_HIF_SDIO
+    //prHif->prFuncInfo = ((MTK_WCN_HIF_SDIO_FUNCINFO *) u4Cookie);
+    prHif->prFuncInfo = prFunc;
+    prHif->cltCtx = *((MTK_WCN_HIF_SDIO_CLTCTX *) u4Cookie);
+    mtk_wcn_hif_sdio_set_drvdata(prHif->cltCtx, prGlueInfo);
+
+#else
+    prHif->func = (struct sdio_func *) u4Cookie;
+
+    //printk(KERN_INFO DRV_NAME"prHif->func->dev = 0x%p\n", &prHif->func->dev);
+    //printk(KERN_INFO DRV_NAME"prHif->func->vendor = 0x%04X\n", prHif->func->vendor);
+    //printk(KERN_INFO DRV_NAME"prHif->func->device = 0x%04X\n", prHif->func->device);
+    //printk(KERN_INFO DRV_NAME"prHif->func->func = 0x%04X\n", prHif->func->num);
+
+    sdio_set_drvdata(prHif->func, prGlueInfo);
+
+    SET_NETDEV_DEV(prGlueInfo->prDevHandler, &prHif->func->dev);
+#endif
+
+    return;
+} /* end of glSetHifInfo() */
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief This function clears hif related info.
+*
+* \param[in] prGlueInfo Pointer to glue info structure
+*
+* \return (none)
+*/
+/*----------------------------------------------------------------------------*/
+VOID
+glClearHifInfo (
+    P_GLUE_INFO_T prGlueInfo
+    )
+{
+    //P_GL_HIF_INFO_T prHif = NULL;
+    //ASSERT(prGlueInfo);
+    //prHif = &prGlueInfo->rHifInfo;
+
+    return;
+} /* end of glClearHifInfo() */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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)
+*/
+/*----------------------------------------------------------------------------*/
+BOOL
+glBusInit (
+    PVOID pvData
+    )
+{
+#if (MTK_WCN_HIF_SDIO == 0)
+    int ret = 0;
+    struct sdio_func *func = NULL;
+
+    ASSERT(pvData);
+
+    func = (struct sdio_func *) pvData;
+
+    sdio_claim_host(func);
+    ret = sdio_set_block_size(func, 512);
+    sdio_release_host(func);
+
+    if (ret) {
+        //printk(KERN_INFO DRV_NAME"sdio_set_block_size 512 failed!\n");
+    }
+    else {
+        //printk(KERN_INFO DRV_NAME"sdio_set_block_size 512 done!\n");
+    }
+
+    //printk(KERN_INFO DRV_NAME"param: func->cur_blksize(%d)\n", func->cur_blksize);
+    //printk(KERN_INFO DRV_NAME"param: func->max_blksize(%d)\n", func->max_blksize);
+    //printk(KERN_INFO DRV_NAME"param: func->card->host->max_blk_size(%d)\n", func->card->host->max_blk_size);
+    //printk(KERN_INFO DRV_NAME"param: func->card->host->max_blk_count(%d)\n", func->card->host->max_blk_count);
+#endif
+    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
+    )
+{
+
+    return;
+} /* 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
+*/
+/*----------------------------------------------------------------------------*/
+INT_32
+glBusSetIrq (
+    PVOID pvData,
+    PVOID pfnIsr,
+    PVOID pvCookie
+    )
+{
+    int ret = 0;
+
+#if (MTK_WCN_HIF_SDIO == 0)
+    struct net_device *prNetDevice = NULL;
+    P_GLUE_INFO_T prGlueInfo = NULL;
+    P_GL_HIF_INFO_T prHifInfo = NULL;
+
+    ASSERT(pvData);
+    if (!pvData) {
+        return -1;
+    }
+    prNetDevice = (struct net_device *) pvData;
+    prGlueInfo = (P_GLUE_INFO_T) pvCookie;
+    ASSERT(prGlueInfo);
+    if (!prGlueInfo) {
+        return -1;
+    }
+
+    prHifInfo = &prGlueInfo->rHifInfo;
+
+    sdio_claim_host(prHifInfo->func);
+    ret = sdio_claim_irq(prHifInfo->func, mtk_sdio_interrupt);
+    sdio_release_host(prHifInfo->func);
+#else
+               /* hif_sdio case */
+               struct net_device *prNetDevice = NULL;
+               P_GLUE_INFO_T prGlueInfo = NULL;
+       
+               ASSERT(pvData);
+               if (!pvData) {
+                       return -1;
+               }
+               prNetDevice = (struct net_device *) pvData;
+       
+               prGlueInfo = (P_GLUE_INFO_T) pvCookie;
+               ASSERT(prGlueInfo);
+               if (!prGlueInfo) {
+                       return -1;
+               }
+       
+               mtk_wcn_hif_sdio_enable_irq(prGlueInfo->rHifInfo.cltCtx, MTK_WCN_BOOL_TRUE);
+
+#endif
+    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
+    )
+{
+#if (MTK_WCN_HIF_SDIO == 0)
+    struct net_device *prNetDevice = NULL;
+    P_GLUE_INFO_T prGlueInfo = NULL;
+    P_GL_HIF_INFO_T prHifInfo = NULL;
+    int ret = 0;
+
+    ASSERT(pvData);
+    if (!pvData) {
+        //printk(KERN_INFO DRV_NAME"%s null pvData\n", __FUNCTION__);
+        return;
+    }
+    prNetDevice = (struct net_device *) pvData;
+    prGlueInfo = (P_GLUE_INFO_T) pvCookie;
+    ASSERT(prGlueInfo);
+    if (!prGlueInfo) {
+        //printk(KERN_INFO DRV_NAME"%s no glue info\n", __FUNCTION__);
+        return;
+    }
+
+    prHifInfo = &prGlueInfo->rHifInfo;
+
+    sdio_claim_host(prHifInfo->func);
+    ret = sdio_release_irq(prHifInfo->func);
+    sdio_release_host(prHifInfo->func);
+#else
+               /* hif_sdio case */
+               struct net_device *prNetDevice = NULL;
+               P_GLUE_INFO_T prGlueInfo = NULL;
+       
+               ASSERT(pvData);
+               if (!pvData) {
+                       //printk(KERN_INFO DRV_NAME"%s null pvData\n", __FUNCTION__);
+                       return;
+               }
+               prNetDevice = (struct net_device *) pvData;
+       
+               prGlueInfo = (P_GLUE_INFO_T) pvCookie;
+               ASSERT(prGlueInfo);
+               if (!prGlueInfo) {
+                       //printk(KERN_INFO DRV_NAME"%s no glue info\n", __FUNCTION__);
+                       return;
+               }
+       
+               mtk_wcn_hif_sdio_enable_irq(prGlueInfo->rHifInfo.cltCtx, MTK_WCN_BOOL_FALSE);
+
+#endif
+
+    return;
+} /* end of glBusreeIrq() */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief Read a 32-bit device register
+*
+* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure.
+* \param[in] u4Register Register offset
+* \param[in] pu4Value   Pointer to variable used to store read value
+*
+* \retval TRUE          operation success
+* \retval FALSE         operation fail
+*/
+/*----------------------------------------------------------------------------*/
+BOOL
+kalDevRegRead (
+    IN  P_GLUE_INFO_T   prGlueInfo,
+    IN  UINT_32         u4Register,
+    OUT PUINT_32        pu4Value
+    )
+{
+    int ret = 0;
+
+    ASSERT(prGlueInfo);
+    ASSERT(pu4Value);
+
+#if MTK_WCN_HIF_SDIO
+    ret = mtk_wcn_hif_sdio_readl(prGlueInfo->rHifInfo.cltCtx, u4Register, (PUINT32) pu4Value);
+#else
+    if (!in_interrupt) {
+        sdio_claim_host(prGlueInfo->rHifInfo.func);
+    }
+
+    *pu4Value = sdio_readl(prGlueInfo->rHifInfo.func, u4Register, &ret);
+
+    if (!in_interrupt) {
+        sdio_release_host(prGlueInfo->rHifInfo.func);
+    }
+#endif
+
+    if (ret) {
+        kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, HIF_SDIO_ERR_DESC_STR "sdio_readl() reports error: %x", ret);
+        DBGLOG(HAL, ERROR, ("sdio_readl() reports error: %x", ret));
+    }
+
+    return (ret) ? FALSE : TRUE;
+} /* end of kalDevRegRead() */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief Write a 32-bit device register
+*
+* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure.
+* \param[in] u4Register Register offset
+* \param[in] u4Value    Value to be written
+*
+* \retval TRUE          operation success
+* \retval FALSE         operation fail
+*/
+/*----------------------------------------------------------------------------*/
+BOOL
+kalDevRegWrite (
+    IN P_GLUE_INFO_T  prGlueInfo,
+    IN UINT_32        u4Register,
+    IN UINT_32        u4Value
+    )
+{
+    int ret = 0;
+
+    ASSERT(prGlueInfo);
+
+#if MTK_WCN_HIF_SDIO
+    ret = mtk_wcn_hif_sdio_writel(prGlueInfo->rHifInfo.cltCtx, u4Register, u4Value);
+#else
+    if (!in_interrupt) {
+        sdio_claim_host(prGlueInfo->rHifInfo.func);
+    }
+
+    sdio_writel(prGlueInfo->rHifInfo.func, u4Value, u4Register, &ret);
+
+    if (!in_interrupt) {
+        sdio_release_host(prGlueInfo->rHifInfo.func);
+    }
+#endif
+
+    if (ret) {
+        kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, HIF_SDIO_ERR_DESC_STR "sdio_writel() reports error: %x", ret);
+        DBGLOG(HAL, ERROR, ("sdio_writel() reports error: %x", ret));
+    }
+
+    return (ret) ? FALSE : TRUE;
+} /* end of kalDevRegWrite() */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief Read device I/O port
+*
+* \param[in] prGlueInfo         Pointer to the GLUE_INFO_T structure.
+* \param[in] u2Port             I/O port offset
+* \param[in] u2Len              Length to be read
+* \param[out] pucBuf            Pointer to read buffer
+* \param[in] u2ValidOutBufSize  Length of the buffer valid to be accessed
+*
+* \retval TRUE          operation success
+* \retval FALSE         operation fail
+*/
+/*----------------------------------------------------------------------------*/
+BOOL
+kalDevPortRead (
+    IN  P_GLUE_INFO_T   prGlueInfo,
+    IN  UINT_16         u2Port,
+    IN  UINT_16         u2Len,
+    OUT PUINT_8         pucBuf,
+    IN  UINT_16         u2ValidOutBufSize
+    )
+{
+    P_GL_HIF_INFO_T prHifInfo = NULL;
+    PUINT_8 pucDst = NULL;
+    int count = u2Len;
+    int ret = 0;
+    int bNum = 0;
+
+#if (MTK_WCN_HIF_SDIO == 0)
+    struct sdio_func *prSdioFunc = NULL;
+#endif
+
+    #if DBG
+    //printk(KERN_INFO DRV_NAME"++kalDevPortRead++ buf:0x%p, port:0x%x, length:%d\n", pucBuf, u2Port, u2Len);
+    #endif
+
+    ASSERT(prGlueInfo);
+    prHifInfo = &prGlueInfo->rHifInfo;
+
+    ASSERT(pucBuf);
+    pucDst = pucBuf;
+
+    ASSERT(u2Len <= u2ValidOutBufSize);
+
+#if (MTK_WCN_HIF_SDIO == 0)
+    prSdioFunc = prHifInfo->func;
+
+    ASSERT(prSdioFunc->cur_blksize > 0);
+
+    if (!in_interrupt) {
+        sdio_claim_host(prSdioFunc);
+    }
+
+    /* Split buffer into multiple single block to workaround hifsys */
+    while (count >= prSdioFunc->cur_blksize) {
+        count -= prSdioFunc->cur_blksize;
+        bNum++;
+    }
+    if (count > 0 && bNum > 0) {
+        bNum++;
+    }
+
+    if (bNum > 0) {
+        ret = sdio_readsb(prSdioFunc, pucDst, u2Port, prSdioFunc->cur_blksize * bNum);
+
+#ifdef CONFIG_X86
+        /* ENE workaround */
+        {
+            int tmp;
+            sdio_writel(prSdioFunc, 0x0, SDIO_X86_WORKAROUND_WRITE_MCR, &tmp);
+        }
+#endif
+
+    }
+    else {
+        ret = sdio_readsb(prSdioFunc, pucDst, u2Port, count);
+    }
+
+    if (!in_interrupt) {
+        sdio_release_host(prSdioFunc);
+    }
+#else
+
+    /* Split buffer into multiple single block to workaround hifsys */
+    while (count >= (prGlueInfo->rHifInfo).prFuncInfo->blk_sz) {
+        count -= ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz);
+        bNum++;
+    }
+    if (count > 0 && bNum > 0) {
+        bNum++;
+    }
+
+    if (bNum > 0) {
+        ret = mtk_wcn_hif_sdio_read_buf(prGlueInfo->rHifInfo.cltCtx, u2Port, (PUINT32) pucDst,
+                 ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz) * bNum);
+    }
+    else {
+        ret = mtk_wcn_hif_sdio_read_buf(prGlueInfo->rHifInfo.cltCtx, u2Port, (PUINT32) pucDst, count);
+    }
+#endif
+
+    if (ret) {
+        kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, HIF_SDIO_ERR_DESC_STR "sdio_readsb() reports error: %x", ret);
+        DBGLOG(HAL, ERROR, ("sdio_readsb() reports error: %x", ret));
+    }
+
+    return (ret) ? FALSE : TRUE;
+} /* end of kalDevPortRead() */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief Write device I/O port
+*
+* \param[in] prGlueInfo         Pointer to the GLUE_INFO_T structure.
+* \param[in] u2Port             I/O port offset
+* \param[in] u2Len              Length to be write
+* \param[in] pucBuf             Pointer to write buffer
+* \param[in] u2ValidInBufSize   Length of the buffer valid to be accessed
+*
+* \retval TRUE          operation success
+* \retval FALSE         operation fail
+*/
+/*----------------------------------------------------------------------------*/
+BOOL
+kalDevPortWrite (
+    IN P_GLUE_INFO_T  prGlueInfo,
+    IN UINT_16        u2Port,
+    IN UINT_16        u2Len,
+    IN PUINT_8        pucBuf,
+    IN UINT_16        u2ValidInBufSize
+    )
+{
+    P_GL_HIF_INFO_T prHifInfo = NULL;
+    PUINT_8 pucSrc = NULL;
+    int count = u2Len;
+    int ret = 0;
+    int bNum = 0;
+
+#if (MTK_WCN_HIF_SDIO == 0)
+    struct sdio_func *prSdioFunc = NULL;
+#endif
+
+    #if DBG
+    //printk(KERN_INFO DRV_NAME"++kalDevPortWrite++ buf:0x%p, port:0x%x, length:%d\n", pucBuf, u2Port, u2Len);
+    #endif
+
+    ASSERT(prGlueInfo);
+    prHifInfo = &prGlueInfo->rHifInfo;
+
+    ASSERT(pucBuf);
+    pucSrc = pucBuf;
+
+    ASSERT(u2Len <= u2ValidInBufSize);
+
+#if (MTK_WCN_HIF_SDIO == 0)
+    prSdioFunc = prHifInfo->func;
+    ASSERT(prSdioFunc->cur_blksize > 0);
+
+    if (!in_interrupt) {
+        sdio_claim_host(prSdioFunc);
+    }
+
+    /* Split buffer into multiple single block to workaround hifsys */
+    while (count >= prSdioFunc->cur_blksize) {
+        count -= prSdioFunc->cur_blksize;
+        bNum++;
+    }
+    if (count > 0 && bNum > 0) {
+        bNum++;
+    }
+
+    if (bNum > 0) { // block mode
+        ret = sdio_writesb(prSdioFunc, u2Port, pucSrc, prSdioFunc->cur_blksize * bNum);
+
+#ifdef CONFIG_X86
+        /* ENE workaround */
+        {
+            int tmp;
+            sdio_writel(prSdioFunc, 0x0, SDIO_X86_WORKAROUND_WRITE_MCR, &tmp);
+        }
+#endif
+
+    }
+    else {  // byte mode
+
+        ret = sdio_writesb(prSdioFunc, u2Port, pucSrc, count);
+    }
+
+    if (!in_interrupt) {
+        sdio_release_host(prSdioFunc);
+    }
+#else
+    /* Split buffer into multiple single block to workaround hifsys */
+    while (count >= ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz)) {
+        count -= ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz);
+        bNum++;
+    }
+    if (count > 0 && bNum > 0) {
+        bNum++;
+    }
+
+    if (bNum > 0) { // block mode
+        ret = mtk_wcn_hif_sdio_write_buf(prGlueInfo->rHifInfo.cltCtx, u2Port, (PUINT32) pucSrc,
+                             ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz) * bNum);
+    }
+    else {  // byte mode
+        ret = mtk_wcn_hif_sdio_write_buf(prGlueInfo->rHifInfo.cltCtx, u2Port, (PUINT32) pucSrc, count);
+    }
+#endif
+
+    if (ret) {
+        kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, HIF_SDIO_ERR_DESC_STR "sdio_writesb() reports error: %x", ret);
+        DBGLOG(HAL, ERROR, ("sdio_writesb() reports error: %x", ret));
+    }
+
+    return (ret) ? FALSE : TRUE;
+} /* end of kalDevPortWrite() */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief Write device I/O port in byte with CMD52
+*
+* \param[in] prGlueInfo         Pointer to the GLUE_INFO_T structure.
+* \param[in] u4Addr             I/O port offset
+* \param[in] ucData             Single byte of data to be written
+*
+* \retval TRUE          operation success
+* \retval FALSE         operation fail
+*/
+/*----------------------------------------------------------------------------*/
+BOOL
+kalDevWriteWithSdioCmd52 (
+    IN P_GLUE_INFO_T    prGlueInfo,
+    IN UINT_32          u4Addr,
+    IN UINT_8           ucData
+    )
+{
+    int ret = 0;
+
+#if (MTK_WCN_HIF_SDIO == 0)
+    if (!in_interrupt) {
+        sdio_claim_host(prGlueInfo->rHifInfo.func);
+    }
+
+    sdio_writeb(prGlueInfo->rHifInfo.func, ucData, u4Addr, &ret);
+
+    if (!in_interrupt) {
+        sdio_release_host(prGlueInfo->rHifInfo.func);
+    }
+#else
+    ret = mtk_wcn_hif_sdio_writeb(prGlueInfo->rHifInfo.cltCtx, u4Addr, ucData);
+#endif
+
+    if (ret) {
+        kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, HIF_SDIO_ERR_DESC_STR "sdio_writeb() reports error: %x", ret);
+        DBGLOG(HAL, ERROR, ("sdio_writeb() reports error: %x", ret));
+    }
+
+    return (ret) ? FALSE : TRUE;
+
+} /* end of kalDevWriteWithSdioCmd52() */
+
+
+VOID
+glSetPowerState (
+    IN P_GLUE_INFO_T  prGlueInfo,
+    IN UINT_32 ePowerMode
+    )
+{
+    return;
+}
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/hif/sdio/x86.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/hif/sdio/x86.c
new file mode 100755 (executable)
index 0000000..4322fa3
--- /dev/null
@@ -0,0 +1,33 @@
+/******************************************************************************
+*[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/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_cfg80211.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_cfg80211.h
new file mode 100755 (executable)
index 0000000..9d00b73
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+** $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 12 2012 wcpadmin
+** [ALPS00276400] Remove MTK copyright and legal header on GPL/LGPL related packages
+** .
+** 
+** 08 29 2012 chinglan.wang
+** [ALPS00349655] [Need Patch] [Volunteer Patch] [ALPS.JB] Daily build warning on [mt6575_phone_mhl-eng]
+** .
+ *
+*/
+
+#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 <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+#include <linux/ieee80211.h>
+#include <net/cfg80211.h>
+
+#include "gl_os.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
+********************************************************************************
+*/
+/* 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_get_station (
+    struct wiphy *wiphy,
+    struct net_device *ndev,
+    u8 *mac,
+    struct station_info *sinfo
+    );
+
+
+int 
+mtk_cfg80211_scan (
+    struct wiphy *wiphy,
+    struct net_device *ndev,
+    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 net_device *ndev,
+    struct ieee80211_channel *chan,
+    enum nl80211_channel_type channel_type,
+    unsigned int duration,
+    u64 *cookie
+    );
+
+
+int
+mtk_cfg80211_cancel_remain_on_channel (
+    struct wiphy *wiphy,
+    struct net_device *ndev,
+    u64 cookie
+    );
+
+
+int
+mtk_cfg80211_mgmt_tx (
+    struct wiphy *wiphy,
+    struct net_device *ndev,
+    struct ieee80211_channel *channel,
+    bool offscan,
+    enum nl80211_channel_type channel_type,
+    bool channel_type_valid,
+    unsigned int wait,
+    const u8 *buf,
+    size_t len,
+    bool no_cck,
+    bool dont_wait_for_ack,
+    u64 *cookie
+    );
+
+
+int
+mtk_cfg80211_mgmt_tx_cancel_wait (
+    struct wiphy *wiphy,
+    struct net_device *ndev,
+    u64 cookie
+    );
+
+#if CONFIG_NL80211_TESTMODE
+int
+mtk_cfg80211_testmode_cmd(
+    IN struct wiphy *wiphy,
+    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
+#else
+    #error "Please ENABLE kernel config (CONFIG_NL80211_TESTMODE) to support Wi-Fi Direct"
+#endif
+
+
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+
+#endif /* _GL_CFG80211_H */
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_kal.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_kal.h
new file mode 100755 (executable)
index 0000000..80861bb
--- /dev/null
@@ -0,0 +1,2250 @@
+/*
+** $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 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 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 similiar 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 continous memory demands
+ * separate kalMemAlloc() into virtually-continous and physically-continous 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 availble 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"
+
+
+#if CFG_ENABLE_BT_OVER_WIFI
+    #include "nic/bow.h"
+#endif
+
+#if DBG
+extern int allocatedMemSize;
+#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 infomation 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 continous */
+    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
+
+/*******************************************************************************
+*                            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 Driver Layer                   */
+/*----------------------------------------------------------------------------*/
+#define KAL_SPIN_LOCK_DECLARATION()             UINT_32 __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;   \
+        printk(KERN_INFO DRV_NAME "0x%p(%ld) allocated (%s:%s)\n", \
+            pvAddr, (UINT_32)u4Size, __FILE__, __FUNCTION__);  \
+    }   \
+    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; \
+            printk(KERN_INFO DRV_NAME "0x%p(%ld) freed (%s:%s)\n", \
+                pvAddr, (UINT_32)u4Size, __FILE__, __FUNCTION__);  \
+        }   \
+        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)
+
+/* 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)   \
+            {struct sk_buff *skb = (struct sk_buff *)pvPacket; \
+             memcpy(pucDestBuffer, skb->data, skb->len);}
+
+#define kalGetTimeTick()                            jiffies_to_msecs(jiffies)
+
+#define kalPrint                                    printk
+
+#if !DBG
+#if CFG_SUPPORT_XLOG
+#define XLOG_TAG   "wlan"
+
+#define XLOG_FUNC(__LEVEL, __FMT...)\
+    if (__LEVEL == ANDROID_LOG_ERROR) {\
+        xlog_printk(ANDROID_LOG_ERROR, XLOG_TAG, ##__FMT);\
+    } \
+    else if (__LEVEL == ANDROID_LOG_WARN) {\
+        xlog_printk(ANDROID_LOG_WARN, XLOG_TAG, ##__FMT);\
+    } \
+    else if (__LEVEL == ANDROID_LOG_INFO) {\
+        xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, ##__FMT);\
+    } \
+    else if (__LEVEL == ANDROID_LOG_DEBUG) {\
+        xlog_printk(ANDROID_LOG_DEBUG, XLOG_TAG, ##__FMT);\
+    } \
+    else if (__LEVEL == ANDROID_LOG_VERBOSE) {\
+        xlog_printk(ANDROID_LOG_VERBOSE, XLOG_TAG, ##__FMT);\
+    }
+
+#define AIS_ERROR_LOGFUNC(_Fmt...)
+#define AIS_WARN_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_WARN, XLOG_TAG, _Fmt)
+#define AIS_INFO_LOGFUNC(_Fmt...)
+#define AIS_STATE_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, _Fmt)
+#define AIS_EVENT_LOGFUNC(_Fmt...)
+#define AIS_TRACE_LOGFUNC(_Fmt...)
+#define AIS_LOUD_LOGFUNC(_Fmt...)
+#define AIS_TEMP_LOGFUNC(_Fmt...)
+
+#define AIS_ERROR_LOGDUMP8(x, y)
+#define AIS_WARN_LOGDUMP8(x, y)
+#define AIS_INFO_LOGDUMP8(x, y)
+#define AIS_STATE_LOGDUMP8(x, y)
+#define AIS_EVENT_LOGDUMP8(x, y)
+#define AIS_TRACE_LOGDUMP8(x, y)
+#define AIS_LOUD_LOGDUMP8(x, y)
+#define AIS_TEMP_LOGDUMP8(x, y)
+
+#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 INTR_ERROR_LOGDUMP8(x, y)
+#define INTR_WARN_LOGDUMP8(x, y)
+#define INTR_INFO_LOGDUMP8(x, y)
+#define INTR_STATE_LOGDUMP8(x, y)
+#define INTR_EVENT_LOGDUMP8(x, y)
+#define INTR_TRACE_LOGDUMP8(x, y)
+#define INTR_LOUD_LOGDUMP8(x, y)
+#define INTR_TEMP_LOGDUMP8(x, y)
+
+#define INIT_ERROR_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_ERROR, XLOG_TAG, _Fmt)
+#define INIT_WARN_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_WARN, XLOG_TAG, _Fmt)
+#define INIT_INFO_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, _Fmt)
+#define INIT_STATE_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, _Fmt)
+#define INIT_EVENT_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, _Fmt)
+#define INIT_TRACE_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_DEBUG, XLOG_TAG, _Fmt)
+#define INIT_LOUD_LOGFUNC(_Fmt...)
+#define INIT_TEMP_LOGFUNC(_Fmt...)
+
+#define INIT_ERROR_LOGDUMP8(x, y)
+#define INIT_WARN_LOGDUMP8(x, y)
+#define INIT_INFO_LOGDUMP8(x, y)
+#define INIT_STATE_LOGDUMP8(x, y)
+#define INIT_EVENT_LOGDUMP8(x, y)
+#define INIT_TRACE_LOGDUMP8(x, y)
+#define INIT_LOUD_LOGDUMP8(x, y)
+#define INIT_TEMP_LOGDUMP8(x, y)
+
+#define AAA_ERROR_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_ERROR, XLOG_TAG, _Fmt)
+#define AAA_WARN_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_WARN, XLOG_TAG, _Fmt)
+#define AAA_INFO_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, _Fmt)
+#define AAA_STATE_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, _Fmt)
+#define AAA_EVENT_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, _Fmt)
+#define AAA_TRACE_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_DEBUG, XLOG_TAG, _Fmt)
+#define AAA_LOUD_LOGFUNC(_Fmt...)
+#define AAA_TEMP_LOGFUNC(_Fmt...)
+
+#define AAA_ERROR_LOGDUMP8(x, y)
+#define AAA_WARN_LOGDUMP8(x, y)
+#define AAA_INFO_LOGDUMP8(x, y)
+#define AAA_STATE_LOGDUMP8(x, y)
+#define AAA_EVENT_LOGDUMP8(x, y)
+#define AAA_TRACE_LOGDUMP8(x, y)
+#define AAA_LOUD_LOGDUMP8(x, y)
+#define AAA_TEMP_LOGDUMP8(x, y)
+
+#define ROAMING_ERROR_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_ERROR, XLOG_TAG, _Fmt)
+#define ROAMING_WARN_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_WARN, XLOG_TAG, _Fmt)
+#define ROAMING_INFO_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, _Fmt)
+#define ROAMING_STATE_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, _Fmt)
+#define ROAMING_EVENT_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, _Fmt)
+#define ROAMING_TRACE_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_DEBUG, XLOG_TAG, _Fmt)
+#define ROAMING_LOUD_LOGFUNC(_Fmt...)
+#define ROAMING_TEMP_LOGFUNC(_Fmt...)
+
+#define ROAMING_ERROR_LOGDUMP8(x, y)
+#define ROAMING_WARN_LOGDUMP8(x, y)
+#define ROAMING_INFO_LOGDUMP8(x, y)
+#define ROAMING_STATE_LOGDUMP8(x, y)
+#define ROAMING_EVENT_LOGDUMP8(x, y)
+#define ROAMING_TRACE_LOGDUMP8(x, y)
+#define ROAMING_LOUD_LOGDUMP8(x, y)
+#define ROAMING_TEMP_LOGDUMP8(x, y)
+
+#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 REQ_ERROR_LOGDUMP8(x, y)
+#define REQ_WARN_LOGDUMP8(x, y)
+#define REQ_INFO_LOGDUMP8(x, y)
+#define REQ_STATE_LOGDUMP8(x, y)
+#define REQ_EVENT_LOGDUMP8(x, y)
+#define REQ_TRACE_LOGDUMP8(x, y)
+#define REQ_LOUD_LOGDUMP8(x, y)
+#define REQ_TEMP_LOGDUMP8(x, y)
+
+#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...)
+#define TX_LOUD_LOGFUNC(_Fmt...)
+#define TX_TEMP_LOGFUNC(_Fmt...)
+
+#define TX_ERROR_LOGDUMP8(x, y)
+#define TX_WARN_LOGDUMP8(x, y)
+#define TX_INFO_LOGDUMP8(x, y)
+#define TX_STATE_LOGDUMP8(x, y)
+#define TX_EVENT_LOGDUMP8(x, y)
+#define TX_TRACE_LOGDUMP8(x, y)
+#define TX_LOUD_LOGDUMP8(x, y)
+#define TX_TEMP_LOGDUMP8(x, y)
+
+#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 RX_ERROR_LOGDUMP8(x, y)
+#define RX_WARN_LOGDUMP8(x, y)
+#define RX_INFO_LOGDUMP8(x, y)
+#define RX_STATE_LOGDUMP8(x, y)
+#define RX_EVENT_LOGDUMP8(x, y)
+#define RX_TRACE_LOGDUMP8(x, y)
+#define RX_LOUD_LOGDUMP8(x, y)
+#define RX_TEMP_LOGDUMP8(x, y)
+
+#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 RFTEST_ERROR_LOGDUMP8(x, y)
+#define RFTEST_WARN_LOGDUMP8(x, y)
+#define RFTEST_INFO_LOGDUMP8(x, y)
+#define RFTEST_STATE_LOGDUMP8(x, y)
+#define RFTEST_EVENT_LOGDUMP8(x, y)
+#define RFTEST_TRACE_LOGDUMP8(x, y)
+#define RFTEST_LOUD_LOGDUMP8(x, y)
+#define RFTEST_TEMP_LOGDUMP8(x, y)
+
+#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 EMU_ERROR_LOGDUMP8(x, y)
+#define EMU_WARN_LOGDUMP8(x, y)
+#define EMU_INFO_LOGDUMP8(x, y)
+#define EMU_STATE_LOGDUMP8(x, y)
+#define EMU_EVENT_LOGDUMP8(x, y)
+#define EMU_TRACE_LOGDUMP8(x, y)
+#define EMU_LOUD_LOGDUMP8(x, y)
+#define EMU_TEMP_LOGDUMP8(x, y)
+
+#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 HEM_ERROR_LOGDUMP8(x, y)
+#define HEM_WARN_LOGDUMP8(x, y)
+#define HEM_INFO_LOGDUMP8(x, y)
+#define HEM_STATE_LOGDUMP8(x, y)
+#define HEM_EVENT_LOGDUMP8(x, y)
+#define HEM_TRACE_LOGDUMP8(x, y)
+#define HEM_LOUD_LOGDUMP8(x, y)
+#define HEM_TEMP_LOGDUMP8(x, y)
+
+#define RLM_ERROR_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_ERROR, XLOG_TAG, _Fmt)
+#define RLM_WARN_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_WARN, XLOG_TAG, _Fmt)
+#define RLM_INFO_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, _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 RLM_ERROR_LOGDUMP8(x, y)
+#define RLM_WARN_LOGDUMP8(x, y)
+#define RLM_INFO_LOGDUMP8(x, y)
+#define RLM_STATE_LOGDUMP8(x, y)
+#define RLM_EVENT_LOGDUMP8(x, y)
+#define RLM_TRACE_LOGDUMP8(x, y)
+#define RLM_LOUD_LOGDUMP8(x, y)
+#define RLM_TEMP_LOGDUMP8(x, y)
+
+#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 MEM_ERROR_LOGDUMP8(x, y)
+#define MEM_WARN_LOGDUMP8(x, y)
+#define MEM_INFO_LOGDUMP8(x, y)
+#define MEM_STATE_LOGDUMP8(x, y)
+#define MEM_EVENT_LOGDUMP8(x, y)
+#define MEM_TRACE_LOGDUMP8(x, y)
+#define MEM_LOUD_LOGDUMP8(x, y)
+#define MEM_TEMP_LOGDUMP8(x, y)
+
+#define CNM_ERROR_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_ERROR, XLOG_TAG, _Fmt)
+#define CNM_WARN_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_WARN, XLOG_TAG, _Fmt)
+#define CNM_INFO_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, _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 CNM_ERROR_LOGDUMP8(x, y)
+#define CNM_WARN_LOGDUMP8(x, y)
+#define CNM_INFO_LOGDUMP8(x, y)
+#define CNM_STATE_LOGDUMP8(x, y)
+#define CNM_EVENT_LOGDUMP8(x, y)
+#define CNM_TRACE_LOGDUMP8(x, y)
+#define CNM_LOUD_LOGDUMP8(x, y)
+#define CNM_TEMP_LOGDUMP8(x, y)
+
+#define RSN_ERROR_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_ERROR, XLOG_TAG, _Fmt)
+#define RSN_WARN_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_WARN, XLOG_TAG, _Fmt)
+#define RSN_INFO_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, _Fmt)
+#define RSN_STATE_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, _Fmt)
+#define RSN_EVENT_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, _Fmt)
+#define RSN_TRACE_LOGFUNC(_Fmt...)
+#define RSN_LOUD_LOGFUNC(_Fmt...)
+#define RSN_TEMP_LOGFUNC(_Fmt...)
+
+#define RSN_ERROR_LOGDUMP8(x, y)
+#define RSN_WARN_LOGDUMP8(x, y)
+#define RSN_INFO_LOGDUMP8(x, y)
+#define RSN_STATE_LOGDUMP8(x, y)
+#define RSN_EVENT_LOGDUMP8(x, y)
+#define RSN_TRACE_LOGDUMP8(x, y)
+#define RSN_LOUD_LOGDUMP8(x, y)
+#define RSN_TEMP_LOGDUMP8(x, y)
+
+#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 BSS_ERROR_LOGDUMP8(x, y)
+#define BSS_WARN_LOGDUMP8(x, y)
+#define BSS_INFO_LOGDUMP8(x, y)
+#define BSS_STATE_LOGDUMP8(x, y)
+#define BSS_EVENT_LOGDUMP8(x, y)
+#define BSS_TRACE_LOGDUMP8(x, y)
+#define BSS_LOUD_LOGDUMP8(x, y)
+#define BSS_TEMP_LOGDUMP8(x, y)
+
+#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 SCN_ERROR_LOGDUMP8(x, y)
+#define SCN_WARN_LOGDUMP8(x, y)
+#define SCN_INFO_LOGDUMP8(x, y)
+#define SCN_STATE_LOGDUMP8(x, y)
+#define SCN_EVENT_LOGDUMP8(x, y)
+#define SCN_TRACE_LOGDUMP8(x, y)
+#define SCN_LOUD_LOGDUMP8(x, y)
+#define SCN_TEMP_LOGDUMP8(x, y)
+
+#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 SAA_ERROR_LOGDUMP8(x, y)
+#define SAA_WARN_LOGDUMP8(x, y)
+#define SAA_INFO_LOGDUMP8(x, y)
+#define SAA_STATE_LOGDUMP8(x, y)
+#define SAA_EVENT_LOGDUMP8(x, y)
+#define SAA_TRACE_LOGDUMP8(x, y)
+#define SAA_LOUD_LOGDUMP8(x, y)
+#define SAA_TEMP_LOGDUMP8(x, y)
+
+#define P2P_ERROR_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_ERROR, XLOG_TAG, _Fmt) 
+#define P2P_WARN_LOGFUNC(_Fmt...)  xlog_printk(ANDROID_LOG_WARN, XLOG_TAG, _Fmt) 
+#define P2P_INFO_LOGFUNC(_Fmt...)  xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, _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 P2P_ERROR_LOGDUMP8(x, y)
+#define P2P_WARN_LOGDUMP8(x, y)
+#define P2P_INFO_LOGDUMP8(x, y)
+#define P2P_STATE_LOGDUMP8(x, y)
+#define P2P_EVENT_LOGDUMP8(x, y)
+#define P2P_TRACE_LOGDUMP8(x, y)
+#define P2P_LOUD_LOGDUMP8(x, y)
+#define P2P_TEMP_LOGDUMP8(x, y)
+
+#define QM_ERROR_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_ERROR, XLOG_TAG, _Fmt)
+#define QM_WARN_LOGFUNC(_Fmt...)  xlog_printk(ANDROID_LOG_WARN, XLOG_TAG, _Fmt)
+#define QM_INFO_LOGFUNC(_Fmt...)  xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, _Fmt)
+#define QM_STATE_LOGFUNC(_Fmt...)
+#define QM_EVENT_LOGFUNC(_Fmt...)
+#define QM_TRACE_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_DEBUG, XLOG_TAG, _Fmt)
+#define QM_LOUD_LOGFUNC(_Fmt...)
+#define QM_TEMP_LOGFUNC(_Fmt...)
+
+#define QM_ERROR_LOGDUMP8(x, y)
+#define QM_WARN_LOGDUMP8(x, y)
+#define QM_INFO_LOGDUMP8(x, y)
+#define QM_STATE_LOGDUMP8(x, y)
+#define QM_EVENT_LOGDUMP8(x, y)
+#define QM_TRACE_LOGDUMP8(x, y)
+#define QM_LOUD_LOGDUMP8(x, y)
+#define QM_TEMP_LOGDUMP8(x, y)
+
+#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 SEC_ERROR_LOGDUMP8(x, y)
+#define SEC_WARN_LOGDUMP8(x, y)
+#define SEC_INFO_LOGDUMP8(x, y)
+#define SEC_STATE_LOGDUMP8(x, y)
+#define SEC_EVENT_LOGDUMP8(x, y)
+#define SEC_TRACE_LOGDUMP8(x, y)
+#define SEC_LOUD_LOGDUMP8(x, y)
+#define SEC_TEMP_LOGDUMP8(x, y)
+
+#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 BOW_ERROR_LOGDUMP8(x, y)
+#define BOW_WARN_LOGDUMP8(x, y)
+#define BOW_INFO_LOGDUMP8(x, y)
+#define BOW_STATE_LOGDUMP8(x, y)
+#define BOW_EVENT_LOGDUMP8(x, y)
+#define BOW_TRACE_LOGDUMP8(x, y)
+#define BOW_LOUD_LOGDUMP8(x, y)
+#define BOW_TEMP_LOGDUMP8(x, y)
+
+#define HAL_ERROR_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_ERROR, XLOG_TAG, _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 HAL_ERROR_LOGDUMP8(x, y)
+#define HAL_WARN_LOGDUMP8(x, y)
+#define HAL_INFO_LOGDUMP8(x, y)
+#define HAL_STATE_LOGDUMP8(x, y)
+#define HAL_EVENT_LOGDUMP8(x, y)
+#define HAL_TRACE_LOGDUMP8(x, y)
+#define HAL_LOUD_LOGDUMP8(x, y)
+#define HAL_TEMP_LOGDUMP8(x, y)
+
+#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 WAPI_ERROR_LOGDUMP8(x, y)
+#define WAPI_WARN_LOGDUMP8(x, y)
+#define WAPI_INFO_LOGDUMP8(x, y)
+#define WAPI_STATE_LOGDUMP8(x, y)
+#define WAPI_EVENT_LOGDUMP8(x, y)
+#define WAPI_TRACE_LOGDUMP8(x, y)
+#define WAPI_LOUD_LOGDUMP8(x, y)
+#define WAPI_TEMP_LOGDUMP8(x, y)
+
+#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 SW1_ERROR_LOGDUMP8(x, y)
+#define SW1_WARN_LOGDUMP8(x, y)
+#define SW1_INFO_LOGDUMP8(x, y)
+#define SW1_STATE_LOGDUMP8(x, y)
+#define SW1_EVENT_LOGDUMP8(x, y)
+#define SW1_TRACE_LOGDUMP8(x, y)
+#define SW1_LOUD_LOGDUMP8(x, y)
+#define SW1_TEMP_LOGDUMP8(x, y)
+
+#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 SW2_ERROR_LOGDUMP8(x, y)
+#define SW2_WARN_LOGDUMP8(x, y)
+#define SW2_INFO_LOGDUMP8(x, y)
+#define SW2_STATE_LOGDUMP8(x, y)
+#define SW2_EVENT_LOGDUMP8(x, y)
+#define SW2_TRACE_LOGDUMP8(x, y)
+#define SW2_LOUD_LOGDUMP8(x, y)
+#define SW2_TEMP_LOGDUMP8(x, y)
+
+#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 SW3_ERROR_LOGDUMP8(x, y)
+#define SW3_WARN_LOGDUMP8(x, y)
+#define SW3_INFO_LOGDUMP8(x, y)
+#define SW3_STATE_LOGDUMP8(x, y)
+#define SW3_EVENT_LOGDUMP8(x, y)
+#define SW3_TRACE_LOGDUMP8(x, y)
+#define SW3_LOUD_LOGDUMP8(x, y)
+#define SW3_TEMP_LOGDUMP8(x, y)
+
+#define SW4_ERROR_LOGFUNC(_Fmt...)
+#define SW4_WARN_LOGFUNC(_Fmt...)
+#define SW4_INFO_LOGFUNC(_Fmt...) xlog_printk(ANDROID_LOG_INFO, XLOG_TAG, _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...)
+
+#define SW4_ERROR_LOGDUMP8(x, y)
+#define SW4_WARN_LOGDUMP8(x, y)
+#define SW4_INFO_LOGDUMP8(x, y)
+#define SW4_STATE_LOGDUMP8(x, y)
+#define SW4_EVENT_LOGDUMP8(x, y)
+#define SW4_TRACE_LOGDUMP8(x, y) dumpMemory8(ANDROID_LOG_DEBUG, x, y)
+#define SW4_LOUD_LOGDUMP8(x, y)
+#define SW4_TEMP_LOGDUMP8(x, y)
+#else
+#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...)
+#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 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
+#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)
+
+/*******************************************************************************
+*                  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 PUINT_32                    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
+    );
+
+BOOL
+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
+    );
+
+
+/*----------------------------------------------------------------------------*/
+/* Routines in interface - ehpi/sdio.c                                                       */
+/*----------------------------------------------------------------------------*/
+BOOL
+kalDevRegRead(
+    IN  P_GLUE_INFO_T  prGlueInfo,
+    IN  UINT_32        u4Register,
+    OUT PUINT_32       pu4Value
+    );
+
+BOOL
+kalDevRegWrite(
+    P_GLUE_INFO_T  prGlueInfo,
+    IN UINT_32     u4Register,
+    IN UINT_32     u4Value
+    );
+
+BOOL
+kalDevPortRead(
+    IN  P_GLUE_INFO_T   prGlueInfo,
+    IN  UINT_16         u2Port,
+    IN  UINT_16         u2Len,
+    OUT PUINT_8         pucBuf,
+    IN  UINT_16         u2ValidOutBufSize
+    );
+
+BOOL
+kalDevPortWrite(
+    P_GLUE_INFO_T  prGlueInfo,
+    IN UINT_16     u2Port,
+    IN UINT_16     u2Len,
+    IN PUINT_8     pucBuf,
+    IN UINT_16     u2ValidInBufSize
+    );
+
+BOOL
+kalDevWriteWithSdioCmd52 (
+    IN P_GLUE_INFO_T    prGlueInfo,
+    IN UINT_32          u4Addr,
+    IN UINT_8           ucData
+    );
+
+
+    #if CFG_SUPPORT_EXT_CONFIG
+UINT_32
+kalReadExtCfg (
+    IN P_GLUE_INFO_T prGlueInfo
+    );
+    #endif
+
+BOOL
+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
+);
+
+inline 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 BOOL                     fgRead,
+    IN BOOL                     fgWaitResp,
+    IN BOOL                     fgCmd,
+    IN BOOL                     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 (unsigned long arg);
+
+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
+    );
+
+BOOL
+kalIsAPmode(
+    IN P_GLUE_INFO_T           prGlueInfo
+    );
+
+#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
+    );
+
+
+
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+
+int tx_thread(void *data);
+
+#endif /* _GL_KAL_H */
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_os.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_os.h
new file mode 100755 (executable)
index 0000000..4a5c3dc
--- /dev/null
@@ -0,0 +1,1140 @@
+/*
+** $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   64  /* packets */
+#define CFG_TX_START_NETIF_PER_QUEUE_THRESHOLD  32  /* 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 IPVERSION                               4
+#define IP_HEADER_LEN                           20
+
+#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(MT5931)
+    #define CHIP_NAME    "MT5931"
+#elif defined(MT6628)
+    #define CHIP_NAME    "MT6628"
+#endif
+
+#define DRV_NAME "["CHIP_NAME"]: "
+
+/* Define if target platform is Android.
+ * It should already be defined in Android kernel source
+ */
+#ifndef CONFIG_ANDROID
+#define CONFIG_ANDROID      0
+#endif
+
+/* 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 <linux/version.h>      /* constant of kernel version */
+
+#include <linux/kernel.h>       /* bitops.h */
+
+#include <linux/timer.h>        /* struct timer_list */
+#include <linux/jiffies.h>      /* jiffies */
+#include <linux/delay.h>        /* udelay and mdelay macro */
+
+#if CONFIG_ANDROID
+#include <linux/wakelock.h>
+#endif
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 12)
+#include <linux/irq.h>          /* IRQT_FALLING */
+#include <linux/hardirq.h>      /*for in_interrupt*/
+#endif
+
+#include <linux/netdevice.h>    /* struct net_device, struct net_device_stats */
+#include <linux/etherdevice.h>  /* for eth_type_trans() function */
+#include <linux/wireless.h>     /* struct iw_statistics */
+#include <linux/if_arp.h>
+#include <linux/inetdevice.h>   /* struct in_device */
+
+#include <linux/ip.h>           /* struct iphdr */
+
+#include <linux/string.h>       /* for memcpy()/memset() function */
+#include <linux/stddef.h>       /* for offsetof() macro */
+
+#include <linux/proc_fs.h>      /* The proc filesystem constants/structures */
+
+#include <linux/rtnetlink.h>    /* for rtnl_lock() and rtnl_unlock() */
+#include <linux/kthread.h>      /* kthread_should_stop(), kthread_run() */
+#include <asm/uaccess.h>        /* for copy_from_user() */
+#include <linux/fs.h>           /* for firmware download */
+#include <linux/vmalloc.h>
+
+#include <linux/kfifo.h>        /* for kfifo interface */
+#include <linux/cdev.h>         /* for cdev interface */
+
+#include <linux/firmware.h>     /* for firmware download */
+
+#if defined(_HIF_SDIO)
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/sdio_func.h>
+#endif
+
+#include <linux/random.h>
+
+#include <linux/lockdep.h>
+
+#include <asm/io.h>             /* readw and writew */
+
+#if WIRELESS_EXT > 12
+#include <net/iw_handler.h>
+#endif
+
+#include "version.h"
+#include "config.h"
+
+#if CFG_ENABLE_WIFI_DIRECT_CFG_80211
+#include <linux/wireless.h>
+#include <net/cfg80211.h>
+#endif
+
+#include <linux/module.h>
+
+#include "gl_typedef.h"
+#include "typedef.h"
+#include "queue.h"
+#include "gl_kal.h"
+#if CFG_CHIP_RESET_SUPPORT
+    #include "gl_rst.h"
+#endif
+#include "hif.h"
+
+
+#include "debug.h"
+
+#include "wlan_lib.h"
+#include "wlan_oid.h"
+
+#if CFG_ENABLE_AEE_MSG
+#include <linux/aee.h>
+#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_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_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;
+    BOOL                    fgRead;
+    BOOL                    fgWaitResp;
+#if CFG_ENABLE_WIFI_DIRECT
+    BOOL                    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
+
+/*
+* 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_32 u4Flag; /* GLUE_FLAG_XXX */
+    UINT_32 u4PendFlag;
+    //UINT_32 u4TimeoutFlag;
+    UINT_32 u4OidCompleteFlag;
+    UINT_32 u4ReadyFlag;  /* check if card is ready */
+
+    /* 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;
+
+    /* NVRAM availability */
+    BOOLEAN                 fgNvramAvailable;
+
+    BOOLEAN                 fgMcrAccessAllowed;
+
+    /* MAC Address Overriden by IOCTL */
+    BOOLEAN                 fgIsMacAddrOverride;
+    PARAM_MAC_ADDRESS       rMacAddrOverride;
+
+    SET_TXPWR_CTRL_T        rTxPwr;
+
+    /* for cfg80211 scan done indication */
+    struct cfg80211_scan_request    *prScanRequest;
+
+    /* 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];
+};
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
+    /* linux 2.4 */
+    typedef void (*PFN_WLANISR)(int irq, void *dev_id, struct pt_regs *regs);
+#else
+    typedef irqreturn_t (*PFN_WLANISR)(int irq, void *dev_id, struct pt_regs *regs);
+#endif
+
+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
+
+#if CONFIG_NL80211_TESTMODE
+
+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;
+    unsigned long    adr;
+    unsigned long    data;
+}NL80211_DRIVER_SW_CMD_PARAMS, *P_NL80211_DRIVER_SW_CMD_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;
+
+
+#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])); \
+            }
+#else /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */
+    #define GLUE_SPIN_LOCK_DECLARATION()                        UINT_32 __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); \
+            }
+#endif /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */
+
+
+/*----------------------------------------------------------------------------*/
+/* Macros for accessing Reserved Fields of native packet                      */
+/*----------------------------------------------------------------------------*/
+#define GLUE_GET_PKT_QUEUE_ENTRY(_p)    \
+            (&( ((struct sk_buff *)(_p))->cb[0] ))
+
+#define GLUE_GET_PKT_DESCRIPTOR(_prQueueEntry)  \
+            ((P_NATIVE_PACKET) ((UINT_32)_prQueueEntry - offsetof(struct sk_buff, cb[0])) )
+
+#define  GLUE_SET_PKT_FLAG_802_11(_p)  \
+            (*((PUINT_8) &( ((struct sk_buff *)(_p))->cb[4] )) |= BIT(7))
+
+#define GLUE_SET_PKT_FLAG_1X(_p)  \
+            (*((PUINT_8) &( ((struct sk_buff *)(_p))->cb[4] )) |= BIT(6))
+
+#define GLUE_SET_PKT_FLAG_PAL(_p)  \
+            (*((PUINT_8) &( ((struct sk_buff *)(_p))->cb[4] )) |= BIT(5))
+
+#define GLUE_SET_PKT_FLAG_P2P(_p)  \
+            (*((PUINT_8) &( ((struct sk_buff *)(_p))->cb[4] )) |= BIT(4))
+
+
+
+#define GLUE_SET_PKT_TID(_p, _tid)  \
+            (*((PUINT_8) &( ((struct sk_buff *)(_p))->cb[4] )) |= (((UINT_8)((_tid) & (BITS(0,3))))))
+
+
+#define GLUE_SET_PKT_FRAME_LEN(_p, _u2PayloadLen) \
+            (*((PUINT_16) &( ((struct sk_buff *)(_p))->cb[6] )) = (UINT_16)(_u2PayloadLen))
+
+#define GLUE_GET_PKT_FRAME_LEN(_p)    \
+            (*((PUINT_16) &( ((struct sk_buff *)(_p))->cb[6] )) )
+
+
+#define  GLUE_GET_PKT_IS_802_11(_p)        \
+            ((*((PUINT_8) &( ((struct sk_buff *)(_p))->cb[4] )) ) & (BIT(7)))
+
+#define  GLUE_GET_PKT_IS_1X(_p)        \
+            ((*((PUINT_8) &( ((struct sk_buff *)(_p))->cb[4] )) ) & (BIT(6)))
+
+#define GLUE_GET_PKT_TID(_p)        \
+            ((*((PUINT_8) &( ((struct sk_buff *)(_p))->cb[4] )) ) & (BITS(0,3)))
+
+
+#define GLUE_GET_PKT_IS_PAL(_p)        \
+            ((*((PUINT_8) &( ((struct sk_buff *)(_p))->cb[4] )) ) & (BIT(5)))
+
+#define GLUE_GET_PKT_IS_P2P(_p)        \
+            ((*((PUINT_8) &( ((struct sk_buff *)(_p))->cb[4] )) ) & (BIT(4)))
+
+
+#define GLUE_SET_PKT_HEADER_LEN(_p, _ucMacHeaderLen)    \
+            (*((PUINT_8) &( ((struct sk_buff *)(_p))->cb[5] )) = (UINT_8)(_ucMacHeaderLen))
+
+#define GLUE_GET_PKT_HEADER_LEN(_p) \
+            (*((PUINT_8) &( ((struct sk_buff *)(_p))->cb[5] )) )
+
+#define GLUE_SET_PKT_ARRIVAL_TIME(_p, _rSysTime) \
+            (*((POS_SYSTIME) &( ((struct sk_buff *)(_p))->cb[8] )) = (OS_SYSTIME)(_rSysTime))
+
+#define GLUE_GET_PKT_ARRIVAL_TIME(_p)    \
+            (*((POS_SYSTIME) &( ((struct sk_buff *)(_p))->cb[8] )) )
+
+/* 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 (
+    struct net_device *prDev,
+    char *pucDevName
+    );
+
+INT_32
+procInitProcfs (
+    struct net_device *prDev,
+    char *pucDevName
+    );
+#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
+p2pSetMulticastListWorkQueueWrapper(
+    P_GLUE_INFO_T prGlueInfo
+    );
+
+
+
+#endif
+
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+
+#endif /* _GL_OS_H */
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_p2p_ioctl.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_p2p_ioctl.h
new file mode 100755 (executable)
index 0000000..9c2ec9d
--- /dev/null
@@ -0,0 +1,1098 @@
+/*
+** $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 paramters
+ *
+ * 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 <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+#if CFG_ENABLE_WIFI_DIRECT_CFG_80211
+    #include <linux/ieee80211.h>
+    #include <net/cfg80211.h>
+#endif
+
+#include "wlan_oid.h"
+
+/*******************************************************************************
+*                              C O N S T A N T S
+********************************************************************************
+*/
+
+// (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
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                           P R I V A T E   D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                                 M A C R O S
+********************************************************************************
+*/
+/* Macros used for cfg80211 */
+#define RATETAB_ENT(_rate, _rateid, _flags) \
+    {                                       \
+        .bitrate    = (_rate),              \
+        .hw_value   = (_rateid),            \
+        .flags      = (_flags),             \
+    }
+
+#define CHAN2G(_channel, _freq, _flags)             \
+    {                                               \
+        .band               = IEEE80211_BAND_2GHZ,  \
+        .center_freq        = (_freq),              \
+        .hw_value           = (_channel),           \
+        .flags              = (_flags),             \
+        .max_antenna_gain   = 0,                    \
+        .max_power          = 30,                   \
+    }
+
+#define CHAN5G(_channel, _flags)                        \
+    {                                                   \
+        .band               = IEEE80211_BAND_5GHZ,      \
+        .center_freq        = 5000 + (5 * (_channel)),  \
+        .hw_value           = (_channel),               \
+        .flags              = (_flags),                 \
+        .max_antenna_gain   = 0,                        \
+        .max_power          = 30,                       \
+    }
+
+/*******************************************************************************
+*                  F U N C T I O N   D E C L A R A T I O N S
+********************************************************************************
+*/
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) && (CFG_ENABLE_WIFI_DIRECT_CFG_80211 != 0)
+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,
+    u8 *mac,
+    struct station_info *sinfo
+    );
+
+int mtk_p2p_cfg80211_scan(
+    struct wiphy *wiphy,
+    struct net_device *ndev,
+    struct cfg80211_scan_request *request
+    );
+
+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_txpower(
+    struct wiphy *wiphy,
+    enum nl80211_tx_power_setting type,
+    int mbm
+    );
+
+int mtk_p2p_cfg80211_get_txpower(
+    struct wiphy *wiphy,
+    int *dbm
+    );
+
+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 net_device * dev,
+    struct ieee80211_channel * chan,
+    enum nl80211_channel_type channel_type,
+    unsigned int duration,
+    u64 * cookie
+    );
+
+int
+mtk_p2p_cfg80211_cancel_remain_on_channel(
+    struct wiphy * wiphy,
+    struct net_device * dev,
+    u64 cookie
+    );
+
+int
+mtk_p2p_cfg80211_deauth(
+    struct wiphy * wiphy,
+    struct net_device * dev,
+    struct cfg80211_deauth_request * req
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)
+    , void *cookie
+#endif
+    );
+
+
+int
+mtk_p2p_cfg80211_disassoc(
+    struct wiphy * wiphy,
+    struct net_device * dev,
+    struct cfg80211_disassoc_request * req
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)
+    , void *cookie
+#endif
+    );
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+
+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 net_device *dev,
+    struct ieee80211_channel *chan,
+    bool offchan,
+    enum nl80211_channel_type channel_type,
+    bool channel_type_valid,
+    unsigned int wait,
+    const u8 *buf, 
+    size_t len, 
+    bool no_cck,
+    bool dont_wait_for_ack,
+    u64 *cookie);
+
+#else
+int
+mtk_p2p_cfg80211_add_set_beacon(
+    struct wiphy *wiphy,
+    struct net_device *dev,
+    struct beacon_parameters *info
+    );
+
+int
+mtk_p2p_cfg80211_mgmt_tx(
+    struct wiphy * wiphy,
+    struct net_device * dev,
+    struct ieee80211_channel * chan,
+    bool offchan,
+    enum nl80211_channel_type channel_type,
+    bool channel_type_valid,
+    unsigned int wait,
+    const u8 * buf,
+    size_t len,
+    u64 *cookie
+    );
+
+#endif
+
+
+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,
+    u8 * mac
+    );
+
+int
+mtk_p2p_cfg80211_set_channel(
+    IN struct wiphy * wiphy,
+    IN struct net_device * dev,
+    IN struct ieee80211_channel * chan,
+    IN enum nl80211_channel_type channel_type
+    );
+
+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
+    );
+
+
+void
+mtk_p2p_cfg80211_mgmt_frame_register(
+    IN struct wiphy *wiphy,
+    IN struct net_device *dev,
+    IN u16 frame_type,
+    IN bool reg
+    );
+
+#if CONFIG_NL80211_TESTMODE
+int
+mtk_p2p_cfg80211_testmode_cmd(
+    IN struct wiphy *wiphy,
+    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_list_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/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_p2p_kal.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_p2p_kal.h
new file mode 100755 (executable)
index 0000000..9a20c26
--- /dev/null
@@ -0,0 +1,395 @@
+/*
+** $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 29 2012 chinglan.wang
+** [ALPS00349655] [Need Patch] [Volunteer Patch] [ALPS.JB] Daily build warning on [mt6575_phone_mhl-eng]
+** .
+ *
+ * 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 "gl_p2p_ioctl.h"
+#include "nic/p2p.h"
+
+
+#if DBG
+    extern int allocatedMemSize;
+#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
+********************************************************************************
+*/
+
+/* 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
+    );
+
+
+VOID
+kalP2PGOStationUpdate(
+    IN P_GLUE_INFO_T prGlueInfo,
+    IN P_STA_RECORD_T prCliStaRec,
+    IN BOOLEAN fgIsNew
+    );
+
+BOOLEAN
+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/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_p2p_os.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_p2p_os.h
new file mode 100755 (executable)
index 0000000..e223249
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+** $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
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                              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         wdev;
+
+    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 */
+    /*move to glueinfo->adapter*/
+   // BOOLEAN                     fgIsRegistered;
+    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;
+
+};
+
+
+BOOLEAN
+p2pRegisterToWlan(
+    P_GLUE_INFO_T prGlueInfo
+    );
+
+BOOLEAN
+p2pUnregisterToWlan(
+    P_GLUE_INFO_T prGlueInfo
+    );
+
+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
+    );
+
+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
+    );
+
+
+#endif
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_rst.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_rst.h
new file mode 100755 (executable)
index 0000000..b85978a
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+** $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
+********************************************************************************
+*/
+/* 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;
+
+typedef enum _ENUM_WMTRSTMSG_TYPE_T{
+    WMTRSTMSG_RESET_START = 0x0,
+    WMTRSTMSG_RESET_END = 0x1,
+    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 */
+    );
+
+
+typedef enum _ENUM_WIFI_NETLINK_GRP_T{
+    WIFI_NETLINK_GRP_RESET,
+    WIFI_NETLINK_GRP_MAX
+} ENUM_WIFI_NETLINK_GRP_T, *P_ENUM_WIFI_NETLINK_GRP_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
+********************************************************************************
+*/
+
+/*----------------------------------------------------------------------------*/
+/* Reset Initialization/Uninitialization                                      */
+/*----------------------------------------------------------------------------*/
+VOID
+glResetInit(
+    VOID
+    );
+
+VOID
+glResetUninit(
+    VOID
+    );
+
+VOID
+glSendResetRequest(
+    VOID
+    );
+
+BOOLEAN
+kalIsResetting(
+    VOID
+    );
+
+
+#endif /* _GL_RST_H */
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_sec.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_sec.h
new file mode 100755 (executable)
index 0000000..16f0af9
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+** $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/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_typedef.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_typedef.h
new file mode 100755 (executable)
index 0000000..e220b43
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+** $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
+
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+#include <linux/earlysuspend.h>
+#endif
+
+/*******************************************************************************
+*                         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               ((BOOL) 0)
+    #define TRUE                ((BOOL) 1)
+#endif /* FALSE */
+
+#ifndef NULL
+    #if defined(__cplusplus)
+        #define NULL            0
+    #else
+        #define NULL            ((void *) 0)
+    #endif
+#endif
+
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+typedef void (*early_suspend_callback)(struct early_suspend *h);
+typedef void (*late_resume_callback) (struct early_suspend *h);
+#endif
+
+
+/*******************************************************************************
+*                             D A T A   T Y P E S
+********************************************************************************
+*/
+/* Type definition for void */
+typedef void                    VOID, *PVOID, **PPVOID;
+
+/* Type definition for Boolean */
+typedef unsigned char           BOOL, *PBOOL, 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 long             INT_32, *PINT_32, **PPINT_32;
+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 long           ULONG, UINT_32, *PUINT_32, **PPUINT_32;
+typedef unsigned long long      UINT_64, *PUINT_64, **PPUINT_64;
+
+typedef unsigned long           OS_SYSTIME, *POS_SYSTIME, **PPOS_SYSTIME;
+
+
+/* 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.
+ * <TODO>: 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);
+
+/*******************************************************************************
+*                            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_INLINE__                  static __inline__
+#define __KAL_ATTRIB_PACKED__           __attribute__((__packed__))
+#define __KAL_ATTRIB_ALIGN_4__          __attribute__ ((aligned (4)))
+
+
+#ifndef BIT
+#define BIT(n)                          ((UINT_32) 1UL << (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)    ((UINT_32)&(((_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)     __constant_ntohs(_x)
+
+    #define CONST_HTONS(_x)     __constant_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/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_wext.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_wext.h
new file mode 100755 (executable)
index 0000000..7a5129f
--- /dev/null
@@ -0,0 +1,376 @@
+/*
+** $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
+    );
+
+int
+wext_get_priv (
+    IN struct net_device *prNetDev,
+    IN struct ifreq *prIfReq
+    );
+
+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
+
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+
+#endif /* WIRELESS_EXT */
+
+#endif /* _GL_WEXT_H */
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_wext_priv.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/include/gl_wext_priv.h
new file mode 100755 (executable)
index 0000000..4a40ce4
--- /dev/null
@@ -0,0 +1,396 @@
+/*
+** $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
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                              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 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
+
+/* 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
+    );
+
+int
+priv_support_ioctl (
+    IN struct net_device *prDev,
+    IN OUT struct ifreq *prReq,
+    IN int i4Cmd
+    );
+
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+
+#endif /* _GL_WEXT_PRIV_H */
+
diff --git a/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/platform.c b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/linux/platform.c
new file mode 100755 (executable)
index 0000000..9eecea2
--- /dev/null
@@ -0,0 +1,620 @@
+/*
+** $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 settting 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 <linux/version.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 12)
+    #include <linux/uaccess.h>
+#endif
+
+#include "gl_os.h"
+
+#ifndef CONFIG_X86
+#if defined(CONFIG_HAS_EARLY_SUSPEND)
+    #include <linux/earlysuspend.h>
+#endif
+#endif
+
+
+extern BOOLEAN fgIsUnderEarlierSuspend;
+
+/*******************************************************************************
+*                              C O N S T A N T S
+********************************************************************************
+*/
+#define WIFI_NVRAM_FILE_NAME   "/data/nvram/APCFG/APRDEB/WIFI"
+#define WIFI_NVRAM_CUSTOM_NAME "/data/nvram/APCFG/APRDEB/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, INFO, ("netdev_event: device is empty.\n"));
+        return NOTIFY_DONE;
+    }
+
+    if ((strncmp(prDev->name, "p2p", 3) != 0) && (strncmp(prDev->name, "wlan", 4) != 0)) {
+        DBGLOG(REQ, INFO, ("netdev_event: xxx\n"));
+        return NOTIFY_DONE;
+    }
+
+    prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+
+    if (prGlueInfo == NULL) {
+        DBGLOG(REQ, INFO, ("netdev_event: prGlueInfo is empty.\n"));
+        return NOTIFY_DONE;
+    }
+    ASSERT(prGlueInfo);
+
+    if (fgIsUnderEarlierSuspend == false) {
+        DBGLOG(REQ, INFO, ("netdev_event: PARAM_MEDIA_STATE_DISCONNECTED. (%d)\n", prGlueInfo->eParamMediaStateIndicated));
+        return NOTIFY_DONE;
+    }
+
+
+
+    // <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 avaliable.\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))){
+        printk(KERN_INFO "ipv6 is not avaliable.\n");
+        return NOTIFY_DONE;
+    }
+
+    kalMemCopy(ip6, &(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local), sizeof(ip6));
+    printk(KERN_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)((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));
+            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)((UINT_32)prParamNetAddr + sizeof(ip6));
+            u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip6);
+       }
+#endif
+        ASSERT(u4Len <= sizeof(aucBuf));
+
+    DBGLOG(REQ, INFO, ("kalIoctl (0x%x, 0x%x)\n", prGlueInfo, prParamNetAddrList));
+
+        rStatus = kalIoctl(prGlueInfo,
+                wlanoidSetNetworkAddress,
+                (PVOID)prParamNetAddrList,
+                u4Len,
+                FALSE,
+                FALSE,
+                TRUE,
+                FALSE,
+                &u4SetInfoLen);
+
+        if (rStatus != WLAN_STATUS_SUCCESS) {
+            DBGLOG(REQ, INFO, ("set HW pattern filter fail 0x%lx\n", rStatus));
+        }
+    }
+
+    return NOTIFY_DONE;
+
+}
+
+static struct notifier_block inetaddr_notifier = {
+    .notifier_call      =   netdev_event,
+};
+
+void wlanRegisterNotifier(void)
+{
+    register_inetaddr_notifier(&inetaddr_notifier);
+}
+
+//EXPORT_SYMBOL(wlanRegisterNotifier);
+
+void wlanUnregisterNotifier(void)
+{
+    unregister_inetaddr_notifier(&inetaddr_notifier);
+}
+
+//EXPORT_SYMBOL(wlanUnregisterNotifier);
+
+#ifndef CONFIG_X86
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief This function will register platform driver to os
+*
+* \param[in] wlanSuspend    Function pointer to platform suspend function
+* \param[in] wlanResume   Function pointer to platform resume   function
+*
+* \return The result of registering earlysuspend
+*/
+/*----------------------------------------------------------------------------*/
+
+int glRegisterEarlySuspend(
+    struct early_suspend        *prDesc,
+    early_suspend_callback      wlanSuspend,
+    late_resume_callback        wlanResume)
+{
+    int ret = 0;
+
+    if(NULL != wlanSuspend)
+        prDesc->suspend = wlanSuspend;
+    else{
+        DBGLOG(REQ, INFO, ("glRegisterEarlySuspend wlanSuspend ERROR.\n"));
+        ret = -1;
+    }
+
+    if(NULL != wlanResume)
+        prDesc->resume = wlanResume;
+    else{
+        DBGLOG(REQ, INFO, ("glRegisterEarlySuspend wlanResume ERROR.\n"));
+        ret = -1;
+    }
+
+    register_early_suspend(prDesc);
+    return ret;
+}
+
+//EXPORT_SYMBOL(glRegisterEarlySuspend);
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief This function will un-register platform driver to os
+*
+* \return The result of un-registering earlysuspend
+*/
+/*----------------------------------------------------------------------------*/
+
+int glUnregisterEarlySuspend(struct early_suspend *prDesc)
+{
+    int ret = 0;
+
+    unregister_early_suspend(prDesc);
+
+    prDesc->suspend = NULL;
+    prDesc->resume = NULL;
+
+    return ret;
+}
+
+//EXPORT_SYMBOL(glUnregisterEarlySuspend);
+#endif
+#endif // !CONFIG_X86
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \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)) {
+            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 = fd->f_op->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 = fd->f_op->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/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/version.h b/drivers/mtk_wcn_combo/drv_wlan/mt6620/wlan/os/version.h
new file mode 100755 (executable)
index 0000000..716a062
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+** $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(MT5931)
+        #define NIC_NAME            "MT5931"
+        #define NIC_DEVICE_ID       "MT5931"
+               #define NIC_DEVICE_ID_LOW   "mt5931"
+    #elif defined(MT6628)
+        #define NIC_NAME            "MT6628"
+        #define NIC_DEVICE_ID       "MT6628"
+               #define NIC_DEVICE_ID_LOW   "mt6628"
+    #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(MT5931)
+    #define NIC_PRODUCT_NAME                "MediaTek Inc. MT5931 Wireless LAN Adapter"
+    #define NIC_DRIVER_NAME                 "MediaTek Inc. MT5931 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"
+#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/mtk_wcn_combo/gps/Makefile b/drivers/mtk_wcn_combo/gps/Makefile
new file mode 100755 (executable)
index 0000000..db3b2a5
--- /dev/null
@@ -0,0 +1,49 @@
+# Copyright Statement:
+#
+# This software/firmware and related documentation ("MediaTek Software") are
+# protected under relevant copyright laws. The information contained herein
+# is confidential and proprietary to MediaTek Inc. and/or its licensors.
+# Without the prior written permission of MediaTek inc. and/or its licensors,
+# any reproduction, modification, use or disclosure of MediaTek Software,
+# and information contained herein, in whole or in part, shall be strictly prohibited.
+
+# MediaTek Inc. (C) 2010. All rights reserved.
+#
+# BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+# THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+# RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+# AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+# NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+# SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+# SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+# THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+# THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+# CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+# SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+# STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+# CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+# AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+# OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+# MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+#
+# The following software/firmware and/or related documentation ("MediaTek Software")
+# have been modified by MediaTek Inc. All revisions are subject to any receiver's
+# applicable license agreements with MediaTek Inc.
+
+
+# drivers/barcelona/gps/Makefile
+#
+# Makefile for the Barcelona GPS driver.
+#
+# Copyright (C) 2004,2005 TomTom BV <http://www.tomtom.com/>
+# Author: Dimitry Andric <dimitry.andric@tomtom.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+
+obj-$(CONFIG_MTK_GPS)          += gps.o
+
+# EOF
diff --git a/drivers/mtk_wcn_combo/gps/gps.c b/drivers/mtk_wcn_combo/gps/gps.c
new file mode 100755 (executable)
index 0000000..c487076
--- /dev/null
@@ -0,0 +1,1138 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ */
+/* MediaTek Inc. (C) 2010. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+
+/* drivers/barcelona/gps/gps.c
+ *
+ * Implementation of the GPS driver.
+ *
+ * Copyright (C) 2004,2005 TomTom BV <http://www.tomtom.com/>
+ * Authors:
+ * Jeroen Taverne <jeroen.taverne@tomtom.com>
+ * Dimitry Andric <dimitry.andric@tomtom.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*******************************************************************************
+* Dependency
+*******************************************************************************/
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/wait.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/poll.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/cdev.h>
+#include <linux/errno.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <linux/semaphore.h>
+#include <linux/version.h>
+
+#if defined(CONFIG_ARCH_MT6573)
+#include <mach/mt6573_devs.h>
+#include <mach/mt6573_typedefs.h>
+#elif defined(CONFIG_ARCH_MT6575)
+#include <mach/mt6575_devs.h>
+#include <mach/mt6575_typedefs.h>
+#elif defined(CONFIG_ARCH_MT6516)
+#include <mach/mt6516_devs.h>
+#include <mach/mt6516_typedefs.h>
+#include <mach/mt6516_gpio.h>
+#include <mach/mt6516_pll.h>
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+struct mt3326_gps_hardware{
+       int (*ext_power_on)(int);
+       int (*ext_power_off)(int);
+};
+
+struct mt3326_gps_hardware mt3326_gps_hw = {
+    .ext_power_on =  NULL,
+    .ext_power_off = NULL,
+};
+
+/****************************************************************************** 
+ * Function Configuration
+******************************************************************************/
+//#define FAKE_DATA  
+#define GPS_SUSPEND_RESUME
+#define GPS_CONFIGURABLE_RESET_DELAY
+/****************************************************************************** 
+ * Definition
+******************************************************************************/
+/* device name and major number */
+#define GPS_DEVNAME            "mt3326-gps"
+/****************************************************************************** 
+ * Debug configuration
+******************************************************************************/
+#define GPS_DBG_NONE(fmt, arg...)    do {} while (0)
+#define GPS_DBG_FUNC(fmt, arg...)    printk(KERN_INFO PFX "%s: " fmt, __FUNCTION__ ,##arg)
+
+#define GPS_ERR(fmt, arg...)         printk(KERN_ERR PFX "%s: " fmt, __FUNCTION__ ,##arg)
+#define GPS_WARN(fmt, arg...)        printk(KERN_WARNING PFX "%s: " fmt, __FUNCTION__ ,##arg)
+#define GPS_NOTICE(fmt, arg...)      printk(KERN_NOTICE PFX "%s: " fmt, __FUNCTION__ ,##arg)
+#define GPS_INFO(fmt, arg...)        printk(KERN_INFO PFX "%s: " fmt, __FUNCTION__ ,##arg)
+#define GPS_TRC_FUNC(f)              printk(PFX "<%s>\n", __FUNCTION__);
+#define GPS_TRC_VERBOSE(fmt, arg...) printk(PFX fmt, ##arg)
+
+#define PFX "GPS: "
+#define GPS_DBG GPS_DBG_FUNC
+#define GPS_TRC GPS_DBG_NONE //GPS_TRC_FUNC
+#define GPS_VER GPS_DBG_NONE //GPS_TRC_VERBOSE
+#define IH_DBG GPS_DBG_NONE
+/*******************************************************************************
+* structure & enumeration
+*******************************************************************************/
+enum {
+    GPS_PWRCTL_UNSUPPORTED  = 0xFF,
+    GPS_PWRCTL_OFF          = 0x00,
+    GPS_PWRCTL_ON           = 0x01,
+    GPS_PWRCTL_RST          = 0x02,
+    GPS_PWRCTL_OFF_FORCE    = 0x03,
+    GPS_PWRCTL_RST_FORCE    = 0x04,
+    GPS_PWRCTL_MAX          = 0x05,
+};
+enum {
+    GPS_PWR_UNSUPPORTED     = 0xFF,
+    GPS_PWR_RESUME          = 0x00,
+    GPS_PWR_SUSPEND         = 0x01,
+    GPS_PWR_MAX             = 0x02,
+};
+enum {
+    GPS_STATE_UNSUPPORTED   = 0xFF,
+    GPS_STATE_OFF           = 0x00, /*cleanup/power off, default state*/
+    GPS_STATE_INIT          = 0x01, /*init*/
+    GPS_STATE_START         = 0x02, /*start navigating*/
+    GPS_STATE_STOP          = 0x03, /*stop navigating*/
+    GPS_STATE_DEC_FREQ      = 0x04, 
+    GPS_STATE_SLEEP         = 0x05,
+    GPS_STATE_MAX           = 0x06,
+};
+enum {
+    GPS_PWRSAVE_UNSUPPORTED = 0xFF,
+    GPS_PWRSAVE_DEC_FREQ    = 0x00,
+    GPS_PWRSAVE_SLEEP       = 0x01,
+    GPS_PWRSAVE_OFF         = 0x02,
+    GPS_PWRSAVE_MAX         = 0x03,
+};
+/*---------------------------------------------------------------------------*/
+struct gps_data{
+    int  dat_len;
+    int  dat_pos;
+    char dat_buf[4096];
+    spinlock_t lock;
+    wait_queue_head_t read_wait;
+    struct semaphore sem;
+};
+/*---------------------------------------------------------------------------*/
+struct gps_sta_itm {    /*gps status record*/
+    unsigned char year;     /*current year - 1900*/
+    unsigned char month;    /*1~12*/
+    unsigned char day;      /*1~31*/
+    unsigned char hour;     /*0~23*/
+    
+    unsigned char minute;      /*0~59*/
+    unsigned char sec;      /*0~59*/
+    unsigned char count;    /*reborn count*/
+    unsigned char reason;   /*reason: 0: timeout; 1: force*/
+};
+/*---------------------------------------------------------------------------*/
+struct gps_sta_obj {
+    int index;
+    struct gps_sta_itm items[32];
+};
+/*---------------------------------------------------------------------------*/
+struct gps_drv_obj {
+    unsigned char pwrctl;
+    unsigned char suspend;
+    unsigned char state;
+    unsigned char pwrsave;
+    int rdelay;   /*power reset delay*/
+    struct kobject *kobj;
+    struct mutex sem;
+    struct gps_sta_obj status;    
+    struct mt3326_gps_hardware *hw;    
+};
+/*---------------------------------------------------------------------------*/
+struct gps_dev_obj {
+    struct class    *cls;
+    struct device   *dev;
+    dev_t           devno;
+    struct cdev     chdev;
+    struct mt3326_gps_hardware *hw;
+};
+/****************************************************************************** 
+ * local variables
+******************************************************************************/
+static struct gps_data gps_private= {0};
+
+#if defined(FAKE_DATA)
+static char fake_data[] = {
+"$GPGGA,135036.000,2446.3713,N,12101.3605,E,1,5,1.61,191.1,M,15.1,M,,*51\r\n"
+"$GPGSA,A,3,22,18,14,30,31,,,,,,,,1.88,1.61,0.98*09\r\n"
+"$GPGSV,2,1,6,18,83,106,32,22,58,324,35,30,45,157,35,14,28,308,32*44\r\n"
+"$GPGSV,2,2,6,40,21,254,,31,17,237,29*42\r\n"
+"$GPRMC,135036.000,A,2446.37125,N,12101.36054,E,0.243,56.48,140109,,A*46\r\n"
+"$GPVTG,56.48,T,,M,0.243,N,0.451,K,A*07\r\n"
+};
+#endif //FAKE_DATA
+
+/*this should be synchronous with mnld.c
+enum { 
+    MNL_RESTART_NONE            = 0x00, //recording the 1st of mnld
+    MNL_RESTART_TIMEOUT_INIT    = 0x01, //restart due to timeout
+    MNL_RESTART_TIMEOUT_MONITOR = 0x02, //restart due to timeout
+    MNL_RESTART_TIMEOUT_WAKEUP  = 0x03, //restart due to timeout
+    MNL_RESTART_TIMEOUT_TTFF    = 0x04, //restart due to TTFF timeout
+    MNL_RESTART_FORCE           = 0x04, //restart due to external command
+};
+*/
+/*---------------------------------------------------------------------------*/
+static char *str_reason[] = {"none", "init", "monitor", "wakeup", "TTFF", "force", "unknown"};
+/****************************************************************************** 
+ * Functions
+******************************************************************************/
+static inline void mt3326_gps_power(struct mt3326_gps_hardware *hw, 
+                                    unsigned int on, unsigned int force)
+{
+    /*FIX ME: PM_api should provide a function to get current status*/    
+    static unsigned int power_on = 1;  
+    int err;
+    GPS_DBG("Switching GPS device %s\n", on ? "on" : "off");
+    if (!hw) {
+        GPS_ERR("null pointer!!\n");
+        return;
+    }
+
+    if (power_on == on) {
+        GPS_DBG("ignore power control: %d\n", on);
+    } else if (on) {
+               /*power on*/
+        if (hw->ext_power_on) {
+            err = hw->ext_power_on(0);
+            if (err)
+                GPS_ERR("ext_power_on fail\n");
+        }
+#if 0
+#ifndef MTK_MT6620 
+               if (!hwPowerOn(MT6516_POWER_V3GTX, VOL_2800,"MT3326")) {
+                       GPS_ERR("power on fails!!\n");
+                       return;
+               }
+#endif
+#endif
+        if (hw->ext_power_on) {
+            err = hw->ext_power_on(1);
+            if (err)
+                GPS_ERR("ext_power_on fail\n");
+        }
+        
+    #if 0
+        if (!hwEnableClock(MT6516_PDN_PERI_UART2,"MT3326"))
+            GPS_ERR("enable clock fail");
+    #endif
+        mdelay(120);
+    } else {    
+    #if 0   
+        if (!hwDisableClock(MT6516_PDN_PERI_UART2,"MT3326"))
+            GPS_ERR("disable clock fail\n");
+    #endif     
+        if (hw->ext_power_off) {
+                             err = hw->ext_power_off(force);
+            if (err)
+                GPS_ERR("ext_power_off fail\n");
+        }
+#if 0
+#ifndef MTK_MT6620
+                if (force) {
+            /*TO FIX: the LDO pin is shared between modem 
+              and external devices, it doesn't work if only
+              calling hwPowerDown*/
+            typedef enum
+            {
+               V3GTX_ENABLE_WITH_SRCLKEN = 0,
+               V3GTX_ENABLE_WITH_V3GTX_EN
+            }v3gtx_on_sel_enum;
+            extern void pmic_v3gtx_on_sel(v3gtx_on_sel_enum);
+            pmic_v3gtx_on_sel(V3GTX_ENABLE_WITH_V3GTX_EN);
+            GPS_DBG("force power off!!\n");
+        }
+        
+        if (!hwPowerDown(MT6516_POWER_V3GTX,"MT3326" ))
+                       GPS_ERR("power off fail\n");
+#endif
+#endif
+    }
+    power_on = on;
+}
+/*****************************************************************************/
+static inline void mt3326_gps_reset(struct mt3326_gps_hardware *hw, int delay, int force) 
+{
+    mt3326_gps_power(hw, 1, FALSE);
+    mdelay(delay); 
+    mt3326_gps_power(hw, 0, force);
+    mdelay(delay);
+    mt3326_gps_power(hw, 1, FALSE);
+}
+/******************************************************************************/
+static inline int mt3326_gps_set_suspend(struct gps_drv_obj* obj,
+                                          unsigned char suspend)
+{
+    if (!obj)
+        return -1;
+    mutex_lock(&obj->sem);
+    if (obj->suspend != suspend) {
+        GPS_DBG("issue sysfs_notify : %p\n", obj->kobj->sd);
+        sysfs_notify(obj->kobj, NULL, "suspend");
+    }
+    obj->suspend = suspend;    
+    mutex_unlock(&obj->sem);
+    return 0;
+}
+/******************************************************************************/
+static inline int mt3326_gps_set_pwrctl(struct gps_drv_obj* obj, 
+                                         unsigned char pwrctl)
+{
+    int err = 0;
+    if (!obj)
+        return -1;
+    mutex_lock(&obj->sem);
+
+    if ((pwrctl == GPS_PWRCTL_ON) || (pwrctl == GPS_PWRCTL_OFF)) {
+        obj->pwrctl = pwrctl;
+        mt3326_gps_power(obj->hw, pwrctl, FALSE);
+    } else if (pwrctl == GPS_PWRCTL_OFF_FORCE) {
+        obj->pwrctl = pwrctl;
+        mt3326_gps_power(obj->hw, pwrctl, TRUE);                
+    } else if (pwrctl == GPS_PWRCTL_RST) {
+        mt3326_gps_reset(obj->hw, obj->rdelay, FALSE);
+        obj->pwrctl = GPS_PWRCTL_ON;
+    } else if (pwrctl == GPS_PWRCTL_RST_FORCE) {
+        mt3326_gps_reset(obj->hw, obj->rdelay, TRUE);
+        obj->pwrctl = GPS_PWRCTL_ON;
+    } else {
+        err = -1;
+    }             
+    mutex_unlock(&obj->sem);    
+    return err;
+}
+ /******************************************************************************/
+static inline int mt3326_gps_set_status(struct gps_drv_obj* obj, 
+                                        const char* buf, size_t count) 
+{
+    int err = 0;
+    int year, mon, day, hour, minute, sec, cnt, reason, idx;
+    if (!obj)
+        return -1;
+
+    mutex_lock(&obj->sem);
+    if (sscanf(buf, "(%d/%d/%d %d:%d:%d) - %d/%d", &year, &mon, &day, 
+               &hour, &minute, &sec, &cnt, &reason) == 8) {
+        int number = (int)(sizeof(obj->status.items)/sizeof(obj->status.items[0]));       
+        idx = obj->status.index % number;
+        obj->status.items[idx].year  = (unsigned char)year;
+        obj->status.items[idx].month = (unsigned char)mon;
+        obj->status.items[idx].day   = (unsigned char)day;
+        obj->status.items[idx].hour  = (unsigned char)hour;
+        obj->status.items[idx].minute= (unsigned char)minute;
+        obj->status.items[idx].sec   = (unsigned char)sec;
+        obj->status.items[idx].count = (unsigned char)cnt;
+        obj->status.items[idx].reason= (unsigned char)reason;
+        obj->status.index ++;
+    } else {
+        err = -1;
+    }
+    mutex_unlock(&obj->sem);
+    return err;
+}
+/******************************************************************************/
+static inline int mt3326_gps_set_state(struct gps_drv_obj* obj, 
+                                       unsigned char state) 
+{
+    int err = 0;
+    if (!obj)
+        return -1;
+    mutex_lock(&obj->sem);
+    if (state < GPS_STATE_MAX) 
+        obj->state = state;        
+    else 
+        err = -1;
+    mutex_unlock(&obj->sem);
+    return err;
+}
+/******************************************************************************/
+static inline int mt3326_gps_set_pwrsave(struct gps_drv_obj* obj, 
+                                         unsigned char pwrsave) 
+{        
+    int err = 0;
+
+    if (!obj)
+        return -1;
+    mutex_lock(&obj->sem);
+    if (pwrsave < GPS_PWRSAVE_MAX) 
+        obj->pwrsave = pwrsave;
+    else 
+        err = -1;
+    mutex_unlock(&obj->sem);
+    return err;
+}
+/******************************************************************************/
+static inline int mt3326_gps_dev_suspend(struct gps_drv_obj *obj) 
+{
+#if defined(GPS_SUSPEND_RESUME) 
+    int err;
+
+    if ((err = mt3326_gps_set_suspend(obj, GPS_PWR_SUSPEND)))
+        GPS_DBG("set suspend fail: %d\n", err);
+    if ((err = mt3326_gps_set_pwrctl(obj, GPS_PWRCTL_OFF)))
+        GPS_DBG("set pwrctl fail: %d\n", err);
+    return err;
+#endif 
+}
+/******************************************************************************/
+static inline int mt3326_gps_dev_resume(struct gps_drv_obj *obj)
+{
+#if defined(GPS_SUSPEND_RESUME)    
+    int err;
+
+    if ((err = mt3326_gps_set_suspend(obj, GPS_PWR_RESUME)))
+        GPS_DBG("set suspend fail: %d\n", err);
+    /*don't power on device automatically*/
+    return err;
+#endif 
+}
+/******************************************************************************/
+static ssize_t mt3326_show_pwrctl(struct device* dev, 
+                                 struct device_attribute *attr, char *buf)
+{
+    struct gps_drv_obj *obj;
+    ssize_t res;
+    if (!dev) {
+        GPS_DBG("dev is null!!\n");
+        return 0;
+    } else if (!(obj = (struct gps_drv_obj*)dev_get_drvdata(dev))) {
+        GPS_DBG("drv data is null!!\n");
+        return 0;
+    }
+    mutex_lock(&obj->sem);
+    res = snprintf(buf, PAGE_SIZE, "%d\n", obj->pwrctl); 
+    mutex_unlock(&obj->sem);
+    return res;
+}
+/******************************************************************************/
+static ssize_t mt3326_store_pwrctl(struct device* dev, struct device_attribute *attr,
+                                  const char *buf, size_t count)
+{
+    struct gps_drv_obj *obj;
+    if (!dev) {
+        GPS_DBG("dev is null!!\n");
+        return 0;
+    } else if (!(obj = (struct gps_drv_obj*)dev_get_drvdata(dev))) {
+        GPS_DBG("drv data is null!!\n");
+        return 0;
+    }   
+    if ((count == 1) ||
+        ((count == 2) && (buf[1] == '\n'))) {
+        unsigned char pwrctl = buf[0] - '0';
+        if (!mt3326_gps_set_pwrctl(obj, pwrctl))
+            return count;
+     }
+    GPS_DBG("invalid content: '%s', length = %d\n", buf, count);
+    return count;
+}
+/******************************************************************************/
+static ssize_t mt3326_show_suspend(struct device* dev, 
+                                   struct device_attribute *attr, char *buf)
+{
+    struct gps_drv_obj *obj;
+    ssize_t res;
+    if (!dev) {
+        GPS_DBG("dev is null!!\n");
+        return 0;
+    } else if (!(obj = (struct gps_drv_obj*)dev_get_drvdata(dev))) {
+        GPS_DBG("drv data is null!!\n");
+        return 0;
+    }
+    mutex_lock(&obj->sem);
+    res = snprintf(buf, PAGE_SIZE, "%d\n", obj->suspend);     
+    mutex_unlock(&obj->sem);
+    return res;
+}
+/******************************************************************************/
+static ssize_t mt3326_store_suspend(struct device* dev, struct device_attribute *attr,
+                                    const char *buf, size_t count)
+{
+    struct gps_drv_obj *obj;
+    if (!dev) {
+        GPS_DBG("dev is null!!\n");
+        return 0;
+    } else if (!(obj = (struct gps_drv_obj*)dev_get_drvdata(dev))) {
+        GPS_DBG("drv data is null!!\n");
+        return 0;
+    }
+    if ((count == 1) ||
+        ((count == 2) && (buf[1] == '\n'))) {
+        unsigned char suspend = buf[0] - '0';
+        if (suspend == GPS_PWR_SUSPEND) {
+            if (!mt3326_gps_dev_suspend(obj))
+                return count;
+        } else if (suspend == GPS_PWR_RESUME) {
+            if (!mt3326_gps_dev_resume(obj))
+                return count;
+        }
+    }
+    GPS_DBG("invalid content: '%s', length = %d\n", buf, count);
+    return count;
+}
+/******************************************************************************/
+static ssize_t mt3326_show_status(struct device* dev, 
+                                  struct device_attribute *attr, char *buf)
+{
+    int res, idx, num, left, cnt, len;
+    struct gps_drv_obj *obj;
+    char *reason = NULL;
+    int reason_max = (int)(sizeof(str_reason)/sizeof(str_reason[0]));
+
+    if (!dev) {
+        GPS_DBG("dev is null!!\n");
+        return 0;
+    } else if (!(obj = (struct gps_drv_obj*)dev_get_drvdata(dev))) {
+        GPS_DBG("drv data is null!!\n");
+        return 0;
+    }
+    mutex_lock(&obj->sem); 
+    num = (int)(sizeof(obj->status.items)/sizeof(obj->status.items[0]));
+    left = PAGE_SIZE;
+    cnt = 0;
+    len = 0;
+    for (idx = 0; idx < num; idx++) {
+        if (obj->status.items[idx].month == 0)
+            continue;
+        if (obj->status.items[idx].reason >= reason_max)
+            reason = str_reason[reason_max-1];
+        else
+            reason = str_reason[obj->status.items[idx].reason];
+        cnt = snprintf(buf+len, left, "[%d] %.4d/%.2d/%.2d %.2d:%.2d:%.2d - %d, %s\n", idx,
+              obj->status.items[idx].year + 1900, obj->status.items[idx].month,
+              obj->status.items[idx].day, obj->status.items[idx].hour, 
+              obj->status.items[idx].minute, obj->status.items[idx].sec,
+              obj->status.items[idx].count, reason);
+        left -= cnt;
+        len += cnt;
+    }
+    res = PAGE_SIZE - left;
+    mutex_unlock(&obj->sem);
+    return res;
+}
+/******************************************************************************/
+static ssize_t mt3326_store_status(struct device* dev, struct device_attribute *attr,
+                                   const char *buf, size_t count)
+{
+    struct gps_drv_obj *obj;
+    if (!dev) {
+        GPS_DBG("dev is null!!\n");
+        return 0;
+    } else if (!(obj = (struct gps_drv_obj*)dev_get_drvdata(dev))) {
+        GPS_DBG("drv data is null!!\n");
+        return 0;
+    }
+    if (!mt3326_gps_set_status(obj, buf, count))
+        return count;
+    GPS_DBG("invalid content: '%s', length = %d\n", buf, count);
+    return count;
+}
+/******************************************************************************/
+static ssize_t mt3326_show_state(struct device* dev, 
+                                 struct device_attribute *attr, char *buf)
+{
+    ssize_t res;
+    struct gps_drv_obj *obj;
+    if (!dev) {
+        GPS_DBG("dev is null!!\n");
+        return 0;
+    } else if (!(obj = (struct gps_drv_obj*)dev_get_drvdata(dev))) {
+        GPS_DBG("drv data is null!!\n");
+        return 0;
+    }
+    mutex_lock(&obj->sem);
+    res = snprintf(buf, PAGE_SIZE, "%d\n", obj->state);     
+    mutex_unlock(&obj->sem);
+    return res;
+}
+/******************************************************************************/
+static ssize_t mt3326_store_state(struct device* dev, struct device_attribute *attr,
+                                  const char *buf, size_t count)
+{
+    struct gps_drv_obj *obj;
+    if (!dev) {
+        GPS_DBG("dev is null!!\n");
+        return 0;
+    } else if (!(obj = (struct gps_drv_obj*)dev_get_drvdata(dev))) {
+        GPS_DBG("drv data is null!!\n");
+        return 0;
+    }
+    if ((count == 1) ||
+        ((count == 2) && (buf[1] == '\n'))) {   /*To Do: dynamic change according to input*/
+        unsigned char state = buf[0] - '0';
+        if (!mt3326_gps_set_state(obj, state))
+            return count;
+    }
+    GPS_DBG("invalid content: '%s', length = %d\n", buf, count);
+    return count;
+}
+/******************************************************************************/
+static ssize_t mt3326_show_pwrsave(struct device* dev, 
+                                   struct device_attribute *attr, char *buf)
+{
+    ssize_t res;
+    struct gps_drv_obj *obj;
+    if (!dev) {
+        GPS_DBG("dev is null!!\n");
+        return 0;
+    } else if (!(obj = (struct gps_drv_obj*)dev_get_drvdata(dev))) {
+        GPS_DBG("drv data is null!!\n");
+        return 0;
+    }
+    mutex_lock(&obj->sem);
+    res = snprintf(buf, PAGE_SIZE, "%d\n", obj->pwrsave);     
+    mutex_unlock(&obj->sem);
+    return res;
+}
+/******************************************************************************/
+static ssize_t mt3326_store_pwrsave(struct device* dev, struct device_attribute *attr,
+                                    const char *buf, size_t count)
+{
+    struct gps_drv_obj *obj;
+    if (!dev) {
+        GPS_DBG("dev is null!!\n");
+        return 0;
+    } else if (!(obj = (struct gps_drv_obj*)dev_get_drvdata(dev))) {
+        GPS_DBG("drv data is null!!\n");
+        return 0;
+    }
+    if ((count == 1) ||
+        ((count == 2) && (buf[1] == '\n'))) {
+        unsigned char pwrsave = buf[0] - '0';
+        if (!mt3326_gps_set_pwrsave(obj, pwrsave))
+            return count;
+    }
+    GPS_DBG("invalid content: '%s', length = %d\n", buf, count);
+    return count;    
+}
+/******************************************************************************/
+#if defined(GPS_CONFIGURABLE_RESET_DELAY)
+/******************************************************************************/
+static ssize_t mt3326_show_rdelay(struct device* dev, 
+                                   struct device_attribute *attr, char *buf)
+{
+    ssize_t res;
+    struct gps_drv_obj *obj;
+    if (!dev) {
+        GPS_DBG("dev is null!!\n");
+        return 0;
+    } else if (!(obj = (struct gps_drv_obj*)dev_get_drvdata(dev))) {
+        GPS_DBG("drv data is null!!\n");
+        return 0;
+    }
+    mutex_lock(&obj->sem);
+    res = snprintf(buf, PAGE_SIZE, "%d\n", obj->rdelay);     
+    mutex_unlock(&obj->sem);
+    return res;
+}
+/******************************************************************************/
+static ssize_t mt3326_store_rdelay(struct device* dev, struct device_attribute *attr,
+                                    const char *buf, size_t count)
+{
+    struct gps_drv_obj *obj;
+    int rdelay;
+    char *end;
+    if (!dev) {
+        GPS_DBG("dev is null!!\n");
+        return 0;
+    } else if (!(obj = (struct gps_drv_obj*)dev_get_drvdata(dev))) {
+        GPS_DBG("drv data is null!!\n");
+        return 0;
+    }
+    end = (char*)buf+count;
+    rdelay = (int)simple_strtol(buf, &end, 10);
+    if (rdelay < 2000) {
+        mutex_lock(&obj->sem);
+        obj->rdelay = rdelay;
+        mutex_unlock(&obj->sem);
+        return count;
+    }
+    GPS_DBG("invalid content: '%s', length = %d\n", buf, count);
+    return count;    
+}
+/******************************************************************************/
+#endif 
+/******************************************************************************/
+DEVICE_ATTR(pwrctl,     S_IWUSR | S_IWGRP | S_IRUGO, mt3326_show_pwrctl,  mt3326_store_pwrctl);
+DEVICE_ATTR(suspend,    S_IWUSR | S_IWGRP | S_IRUGO, mt3326_show_suspend,mt3326_store_suspend);
+DEVICE_ATTR(status,     S_IWUSR | S_IWGRP | S_IRUGO, mt3326_show_status, mt3326_store_status);
+DEVICE_ATTR(state,      S_IWUSR | S_IWGRP | S_IRUGO, mt3326_show_state,  mt3326_store_state);
+DEVICE_ATTR(pwrsave,    S_IWUSR | S_IWGRP | S_IRUGO, mt3326_show_pwrsave,mt3326_store_pwrsave);
+#if defined(GPS_CONFIGURABLE_RESET_DELAY)
+DEVICE_ATTR(rdelay,     S_IWUSR | S_IWGRP | S_IRUGO, mt3326_show_rdelay ,mt3326_store_rdelay);
+#endif 
+static struct device_attribute *gps_attr_list[] = {
+    &dev_attr_pwrctl,
+    &dev_attr_suspend,
+    &dev_attr_status,
+    &dev_attr_state,
+    &dev_attr_pwrsave,
+#if defined(GPS_CONFIGURABLE_RESET_DELAY)
+    &dev_attr_rdelay,
+#endif 
+};
+/******************************************************************************/
+static int mt3326_gps_create_attr(struct device *dev) 
+{
+    int idx, err = 0;
+    int num = (int)(sizeof(gps_attr_list)/sizeof(gps_attr_list[0]));
+    if (!dev)
+        return -EINVAL;
+
+    GPS_TRC();
+    for (idx = 0; idx < num; idx++) {
+        if ((err = device_create_file(dev, gps_attr_list[idx]))) {            
+            GPS_DBG("device_create_file (%s) = %d\n", gps_attr_list[idx]->attr.name, err);        
+            break;
+        }
+    }
+    
+    return err;
+}
+/******************************************************************************/
+static int mt3326_gps_delete_attr(struct device *dev)
+{
+    int idx ,err = 0;
+    int num = (int)(sizeof(gps_attr_list)/sizeof(gps_attr_list[0]));
+    
+    if (!dev)
+        return -EINVAL;
+
+    for (idx = 0; idx < num; idx++) 
+        device_remove_file(dev, gps_attr_list[idx]);
+
+    return err;
+}
+/******************************************************************************/
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36))
+static int mt3326_gps_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+    return -ENOIOCTLCMD;
+}
+#else
+long mt3326_gps_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+    GPS_DBG("mt3326_gps_unlocked_ioctl!!\n");
+    return -ENOIOCTLCMD;
+}
+#endif
+/*****************************************************************************/
+static int mt3326_gps_open(struct inode *inode, struct file *file)
+{
+    GPS_TRC();
+    file->private_data = &gps_private;  //all files share the same buffer
+    return nonseekable_open(inode, file);
+}
+/*****************************************************************************/
+static int mt3326_gps_release(struct inode *inode, struct file *file)
+{
+    struct gps_data *dev = file->private_data;
+
+    GPS_TRC();
+    
+    if (dev) 
+        file->private_data = NULL;   
+    
+    return 0;
+}
+/******************************************************************************/
+static ssize_t mt3326_gps_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+{
+    struct gps_data *dev = file->private_data;
+    ssize_t ret = 0;
+    int copy_len = 0;
+
+    GPS_TRC();
+    
+    if (!dev)
+        return -EINVAL;
+    
+    //printk("%s: %d\n", __FUNCTION__, dev->dat_len);
+    if (signal_pending(current))
+        return -ERESTARTSYS;
+    
+    if (down_interruptible(&dev->sem))
+        return -ERESTARTSYS;
+
+    if (dev->dat_len == 0){ /*no data to be read*/
+        up(&dev->sem);
+        if (file->f_flags & O_NONBLOCK) /*non-block mode*/
+            return -EAGAIN;
+        do {/*block mode*/  
+            ret = wait_event_interruptible(dev->read_wait, (dev->dat_len > 0)); 
+            if (ret == -ERESTARTSYS)
+                return -ERESTARTSYS;
+        }while(ret == 0);
+        if (down_interruptible(&dev->sem))  
+            return -ERESTARTSYS;
+    }
+    
+    /*data is available*/
+    copy_len = (dev->dat_len < (int)count) ? (dev->dat_len) : (int)(count);
+    if (copy_to_user(buf, dev->dat_buf+dev->dat_pos, (unsigned long)copy_len)){
+        GPS_DBG("copy_to_user error: 0x%X 0x%X, %d\n", (unsigned int)buf, (unsigned int)dev->dat_buf, dev->dat_len);
+        ret = -EFAULT;
+    } else {        
+        GPS_VER("mt3326_gps_read(%d,%d,%d) = %d\n", count, dev->dat_pos, dev->dat_len, copy_len);
+        if (dev->dat_len > (copy_len+dev->dat_pos)) {
+            dev->dat_pos += copy_len;
+        } else {        
+            dev->dat_len = 0;
+            dev->dat_pos = 0;
+        }
+        ret = copy_len;
+    }
+    
+    up(&dev->sem);
+    GPS_VER("%s return %d bytes\n", __FUNCTION__, ret);
+    return ret;
+}
+/******************************************************************************/
+static ssize_t mt3326_gps_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+{    
+    struct gps_data *dev = file->private_data;
+    ssize_t ret = 0;
+
+    GPS_TRC();    
+    
+    if (!dev)
+        return -EINVAL;
+    
+    if (!count)     /*no data written*/
+        return 0;
+    
+    if (signal_pending(current))
+        return -ERESTARTSYS;
+    
+    if (down_interruptible(&dev->sem))
+        return -ERESTARTSYS;
+
+    if (copy_from_user(dev->dat_buf, buf, count)) {
+        GPS_DBG("copy_from_user error");
+        ret = -EFAULT;
+    } else {
+        dev->dat_len = count; 
+        dev->dat_pos = 0;
+        ret = count;
+    }
+    up(&dev->sem);
+    wake_up_interruptible(&dev->read_wait);
+    GPS_VER("%s: write %d bytes\n", __FUNCTION__, dev->dat_len);
+    return ret;
+}
+/******************************************************************************/
+static unsigned int mt3326_gps_poll(struct file *file, poll_table *wait)
+{
+    struct gps_data *dev = file->private_data;
+    unsigned int mask = 0;
+
+    GPS_TRC();
+
+    if (!dev)
+        return 0;
+
+    down(&dev->sem);
+    poll_wait(file, &dev->read_wait, wait);    
+    if (dev->dat_len != 0) /*readable if data is available*/
+        mask = (POLLIN|POLLRDNORM) | (POLLOUT|POLLWRNORM);
+    else /*always writable*/
+        mask = (POLLOUT|POLLWRNORM);    
+    up(&dev->sem);
+    GPS_VER("%s: mask : 0x%X\n", __FUNCTION__, mask);
+    return mask;    
+}
+/*****************************************************************************/
+/* Kernel interface */
+static struct file_operations mt3326_gps_fops = {
+    .owner      = THIS_MODULE,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36))
+    .ioctl      = mt3326_gps_ioctl,
+#else
+    .unlocked_ioctl      = mt3326_gps_unlocked_ioctl,
+#endif
+    .open       = mt3326_gps_open,
+    .read       = mt3326_gps_read,
+    .write      = mt3326_gps_write,
+    .release    = mt3326_gps_release,
+    .poll       = mt3326_gps_poll,
+};
+/*****************************************************************************/
+extern unsigned int reset_state;
+/*****************************************************************************/
+static void mt3326_gps_hw_init(struct mt3326_gps_hardware *hw)
+{
+    mt3326_gps_power(hw, 1, FALSE); 
+}
+/*****************************************************************************/
+static void mt3326_gps_hw_exit(struct mt3326_gps_hardware *hw)
+{
+    mt3326_gps_power(hw, 0, FALSE);
+}
+/*****************************************************************************/
+static int mt3326_gps_probe(struct platform_device *dev)
+{
+    int ret = 0, err = 0;
+    struct gps_drv_obj *drvobj = NULL;
+    struct mt3326_gps_hardware *hw = (struct mt3326_gps_hardware*)dev->dev.platform_data;    
+    struct gps_dev_obj *devobj = NULL; 
+
+    if (!(devobj = kzalloc(sizeof(*devobj), GFP_KERNEL)))
+    {
+        GPS_ERR("-ENOMEM\n");
+        err = -ENOMEM;
+        goto error;
+    }
+
+    mt3326_gps_hw_init(hw);
+
+    GPS_DBG("Registering chardev\n");
+    ret = alloc_chrdev_region(&devobj->devno, 0, 1, GPS_DEVNAME);
+    if (ret) {
+        GPS_ERR("alloc_chrdev_region fail: %d\n", ret);
+        goto error;
+    } else {
+        GPS_DBG("major: %d, minor: %d\n", MAJOR(devobj->devno), MINOR(devobj->devno));
+    }
+    cdev_init(&devobj->chdev, &mt3326_gps_fops);
+    devobj->chdev.owner = THIS_MODULE;
+    err = cdev_add(&devobj->chdev, devobj->devno, 1);
+    if (err) {
+        GPS_ERR("cdev_add fail: %d\n", err);
+        goto error;
+    }
+    
+    if (!(drvobj = kmalloc(sizeof(*drvobj), GFP_KERNEL))) {
+        err = -ENOMEM;
+        goto error;
+    }    
+    memset(drvobj, 0 ,sizeof(*drvobj));
+
+    devobj->cls = class_create(THIS_MODULE, "gpsdrv");
+    if (IS_ERR(devobj->cls)) {
+        GPS_ERR("Unable to create class, err = %d\n", (int)PTR_ERR(devobj->cls));
+        goto error;       
+    }
+    devobj->dev = device_create(devobj->cls, NULL, devobj->devno, drvobj, "gps");    
+    drvobj->hw      = hw;
+    drvobj->pwrctl  = 0;
+    drvobj->suspend = 0;
+    drvobj->state   = GPS_STATE_UNSUPPORTED;
+    drvobj->pwrsave = GPS_PWRSAVE_UNSUPPORTED;
+    drvobj->rdelay  = 50;    
+    drvobj->kobj    = &devobj->dev->kobj;
+    mutex_init(&drvobj->sem);
+    
+    if ((err = mt3326_gps_create_attr(devobj->dev)))
+        goto error;        
+    
+    /*initialize members*/
+    spin_lock_init(&gps_private.lock);
+    init_waitqueue_head(&gps_private.read_wait);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36))
+    init_MUTEX(&gps_private.sem);
+#else
+    sema_init(&gps_private.sem, 1);
+#endif
+    gps_private.dat_len = 0;
+    gps_private.dat_pos = 0;
+    memset(gps_private.dat_buf, 0x00, sizeof(gps_private.dat_buf));
+
+    /*set platform data: 
+      a new device created for gps */
+    platform_set_drvdata(dev, devobj);
+    
+    GPS_DBG("Done\n");
+    return 0;
+
+error:
+    if (err == 0)
+        cdev_del(&devobj->chdev);
+    if (ret == 0)
+        unregister_chrdev_region(devobj->devno, 1);
+    return -1;
+}
+/*****************************************************************************/
+static int mt3326_gps_remove(struct platform_device *dev)
+{
+    struct gps_dev_obj *devobj = (struct gps_dev_obj*)platform_get_drvdata(dev);
+    struct gps_drv_obj *drvobj = (struct gps_drv_obj*)dev_get_drvdata(devobj->dev);
+    int err;
+    
+    if (!devobj || !drvobj) {
+        GPS_ERR("null pointer: %p, %p\n", devobj, drvobj);
+        return -1;
+    }
+
+    GPS_DBG("Unregistering chardev\n");
+    kfree(devobj);
+    
+    cdev_del(&devobj->chdev);
+    unregister_chrdev_region(devobj->devno, 1);
+
+    mt3326_gps_hw_exit(devobj->hw);
+    if ((err = mt3326_gps_delete_attr(devobj->dev)))
+        GPS_ERR("delete attr fails: %d\n", err);
+    device_destroy(devobj->cls, devobj->devno);
+    class_destroy(devobj->cls);
+    GPS_DBG("Done\n");
+    return 0;
+}
+/*****************************************************************************/
+static void mt3326_gps_shutdown(struct platform_device *dev)
+{
+    struct gps_dev_obj *devobj = (struct gps_dev_obj*)platform_get_drvdata(dev);    
+    GPS_DBG("Shutting down\n");
+    mt3326_gps_hw_exit(devobj->hw);
+}
+/*****************************************************************************/
+#ifdef CONFIG_PM
+/*****************************************************************************/
+static int mt3326_gps_suspend(struct platform_device *dev, pm_message_t state)
+{
+    int err = 0;    
+    struct gps_dev_obj *devobj = (struct gps_dev_obj*)platform_get_drvdata(dev);
+    struct gps_drv_obj *drvobj = (struct gps_drv_obj*)dev_get_drvdata(devobj->dev);
+    
+    if (!devobj || !drvobj) {
+        GPS_ERR("null pointer: %p, %p\n", devobj, drvobj);
+        return -1;
+    }
+    
+    GPS_DBG("dev = %p, event = %u,", dev, state.event);
+    if (state.event == PM_EVENT_SUSPEND) {
+        err = mt3326_gps_dev_suspend(drvobj);
+    }
+    return err;
+}
+/*****************************************************************************/
+static int mt3326_gps_resume(struct platform_device *dev)
+{
+    struct gps_dev_obj *devobj = (struct gps_dev_obj*)platform_get_drvdata(dev);
+    struct gps_drv_obj *drvobj = (struct gps_drv_obj*)dev_get_drvdata(devobj->dev);
+    
+    GPS_DBG("");
+    return mt3326_gps_dev_resume(drvobj);
+}
+/*****************************************************************************/
+#endif /* CONFIG_PM */
+/*****************************************************************************/
+static struct platform_driver mt3326_gps_driver = 
+{
+    .probe      = mt3326_gps_probe,
+    .remove     = mt3326_gps_remove,
+    .shutdown   = mt3326_gps_shutdown,
+#if defined(CONFIG_PM)    
+    .suspend    = mt3326_gps_suspend,
+    .resume     = mt3326_gps_resume,
+#endif     
+    .driver     = {
+        .name = GPS_DEVNAME,
+        .bus    = &platform_bus_type,
+    },    
+};
+
+struct platform_device mt3326_device_gps = {
+        .name          = "mt3326-gps",
+        .id            = -1,
+        .dev = {
+        .platform_data = &mt3326_gps_hw,
+    },  
+};
+
+/*****************************************************************************/
+static int __init mt3326_gps_mod_init(void)
+{
+    int ret = 0;
+    GPS_TRC();
+
+    //ret = driver_register(&mt3326_gps_driver);
+    ret = platform_driver_register(&mt3326_gps_driver);
+    if (ret != 0){
+        GPS_ERR("platform_driver_register error\n");      
+    }
+    ret = platform_device_register(&mt3326_device_gps);
+
+    if (ret != 0){
+        GPS_ERR("platform_device_register error\n");        
+    } 
+    return ret;
+}
+/*****************************************************************************/
+static void __exit mt3326_gps_mod_exit(void)
+{
+    GPS_TRC();
+    platform_driver_unregister(&mt3326_gps_driver);
+}
+/*****************************************************************************/
+module_init(mt3326_gps_mod_init);
+module_exit(mt3326_gps_mod_exit);
+/*****************************************************************************/
+MODULE_AUTHOR("MingHsien Hsieh <MingHsien.Hsieh@mediatek.com>");
+MODULE_DESCRIPTION("MT3326 GPS Driver");
+MODULE_LICENSE("GPL");
+
+
+
old mode 100644 (file)
new mode 100755 (executable)
index 9898263..eee1ef2
@@ -31,7 +31,7 @@ config CFG80211
 
 config NL80211_TESTMODE
        bool "nl80211 testmode command"
 
 config NL80211_TESTMODE
        bool "nl80211 testmode command"
-       depends on CFG80211 && (MT5931 || MT5931_MT6622)
+       depends on CFG80211 && (MT5931 || MT5931_MT6622 || MTK_COMBO)
        help
          The nl80211 testmode command helps implementing things like
          factory calibration or validation tools for wireless chips.
        help
          The nl80211 testmode command helps implementing things like
          factory calibration or validation tools for wireless chips.