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
 
 #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
 ********************************************************************************
@@ -129,32 +142,6 @@ typedef enum {
     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);
@@ -171,11 +158,17 @@ typedef struct _CMB_STUB_CB_ {
 ********************************************************************************
 */
 
+
+
 /*******************************************************************************
 *                           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
 ********************************************************************************
@@ -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);
 
-#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
 
-/* 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
 ********************************************************************************
 */
 
+
 #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
 
 #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
 ********************************************************************************
@@ -129,32 +142,6 @@ typedef enum {
     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);
@@ -171,11 +158,17 @@ typedef struct _CMB_STUB_CB_ {
 ********************************************************************************
 */
 
+
+
 /*******************************************************************************
 *                           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
 ********************************************************************************
@@ -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);
 
-#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
 
-/* 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
 ********************************************************************************
 */
 
+
 #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"
-       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.